Python - Pandas 计算基尼系数的数据操作
Python - Pandas Data manipulation to calculate Gini Coefficient
我有以下形状的数据集:
tconst GreaterEuropean British WestEuropean Italian French Jewish Germanic Nordic Asian GreaterEastAsian Japanese Hispanic GreaterAfrican Africans EastAsian Muslim IndianSubContinent total_ethnicities
0 tt0000001 3 1 2 0 1 0 0 1 0 0 0 0 0 0 0 0 0 8
1 tt0000002 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 6
2 tt0000003 4 0 3 0 3 1 0 0 0 0 0 0 0 0 0 0 0 11
3 tt0000004 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 6
4 tt0000005 3 2 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 7
这是 IMDB 数据,经过处理后,我创建了这些列,代表一部电影中有这么多民族演员 (tcons)。
我想创建另一个列 df["diversity"]
,它是:
( diversity score "gini index")
例如:
对于每部电影,假设我们有 10 位演员; 3 名亚洲人、3 名英国人、3 名非裔美国人和 1 名法国人。所以我们除以总数
3/10 3/ 10 3/10 1/10
然后 1 减去 ( 3/10 ) 平方的和 ( 3/ 10) 平方 ( 3/10) 平方 (1/10) 平方
将每个演员的分数作为多样性添加到列中。
我正在尝试简单的 pandas 操作,但没有成功。
编辑:
对于第一行,
我们的种族总数为 8
3 GreaterEuropean
1 British
2 WestEuropean
1 French
1 nordic
所以得分将是
1- [(3/8)^2 + (1/8)^2 + (2/8)^2 + (1/8)^2 + (1/8)^2]
您可以在此处使用 numpy 向量化,即
one = df.drop(['total_ethnicities'],1).values
# Select the values other than total_ethnicities
two = df['total_ethnicities'].values[:,None]
# Select the values of total_ethnicities
df['diversity'] = 1 - pd.np.sum((one/two)**2, axis=1)
# Divide the values of one by two, square them. Sum over the axis. Then subtract from 1.
df['diversity']
tconst
tt0000001 0.750000
tt0000002 0.666667
tt0000003 0.710744
tt0000004 0.666667
tt0000005 0.693878
Name: diversity, dtype: float64
df2 = df.set_index('tconst')
total = df2.pop('total_ethnicities')
result = 1 - ((df2** 2 ).div(total**2, axis=0)).sum(axis=1)
result.name = 'gini'
tconst
tt0000001 0.750000
tt0000002 0.666667
tt0000003 0.710744
tt0000004 0.666667
tt0000005 0.693878
Name: gini, dtype: float64
除此之外,我总是尽量将原始数据与解析数据分开,因此我会将列 total_etnicities
放在一个单独的系列中,并且只有在需要报告结果时才会我把它们组合起来
如果您确实希望将此结果作为 df
中的额外列,您可以通过以下方式实现:
df = df.join(result, on='tconst')
执行此操作的最佳方法是将所有列与给定列进行比较,因为基尼系数定义了分布的差异。您将生成比较分布的基尼系数,例如意大利、法国、犹太人。然后,与给定的列进行比较,您甚至可以将这些种族分组为相似分布的集群。
假设 df2 是您的数据框。基尼指数公式为:
您 select Pandas 中的数据透视列 (place_y):
place_y=df2.columns.get_loc("price_doc")
gini=[]
for i in range(0,df2.shape[1]):
gini.append((df2.shape[0]+1-2*(np.sum((df2.shape[0]+1-df2.ix[:,i])*df2.ix[:,place_y])/np.sum(df2.ix[:,place_y])))/df2.shape[0])
然后你 select 最符合你的阈值的列,假设 0.2,最相似的分布:
np.where(np.array(np.abs(gini))<.2)[0]
在您的情况下,您似乎想要比较示例(行)而不是特征(列)以生成新列。这是相同的理性,换位。在您的数据透视行中,基尼系数将为零,而所有其他行都有其系数。
我有以下形状的数据集:
tconst GreaterEuropean British WestEuropean Italian French Jewish Germanic Nordic Asian GreaterEastAsian Japanese Hispanic GreaterAfrican Africans EastAsian Muslim IndianSubContinent total_ethnicities
0 tt0000001 3 1 2 0 1 0 0 1 0 0 0 0 0 0 0 0 0 8
1 tt0000002 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 6
2 tt0000003 4 0 3 0 3 1 0 0 0 0 0 0 0 0 0 0 0 11
3 tt0000004 2 0 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 6
4 tt0000005 3 2 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 7
这是 IMDB 数据,经过处理后,我创建了这些列,代表一部电影中有这么多民族演员 (tcons)。
我想创建另一个列 df["diversity"]
,它是:
( diversity score "gini index")
例如: 对于每部电影,假设我们有 10 位演员; 3 名亚洲人、3 名英国人、3 名非裔美国人和 1 名法国人。所以我们除以总数 3/10 3/ 10 3/10 1/10 然后 1 减去 ( 3/10 ) 平方的和 ( 3/ 10) 平方 ( 3/10) 平方 (1/10) 平方 将每个演员的分数作为多样性添加到列中。
我正在尝试简单的 pandas 操作,但没有成功。
编辑:
对于第一行, 我们的种族总数为 8
3 GreaterEuropean
1 British
2 WestEuropean
1 French
1 nordic
所以得分将是
1- [(3/8)^2 + (1/8)^2 + (2/8)^2 + (1/8)^2 + (1/8)^2]
您可以在此处使用 numpy 向量化,即
one = df.drop(['total_ethnicities'],1).values
# Select the values other than total_ethnicities
two = df['total_ethnicities'].values[:,None]
# Select the values of total_ethnicities
df['diversity'] = 1 - pd.np.sum((one/two)**2, axis=1)
# Divide the values of one by two, square them. Sum over the axis. Then subtract from 1.
df['diversity']
tconst
tt0000001 0.750000
tt0000002 0.666667
tt0000003 0.710744
tt0000004 0.666667
tt0000005 0.693878
Name: diversity, dtype: float64
df2 = df.set_index('tconst')
total = df2.pop('total_ethnicities')
result = 1 - ((df2** 2 ).div(total**2, axis=0)).sum(axis=1)
result.name = 'gini'
tconst tt0000001 0.750000 tt0000002 0.666667 tt0000003 0.710744 tt0000004 0.666667 tt0000005 0.693878 Name: gini, dtype: float64
除此之外,我总是尽量将原始数据与解析数据分开,因此我会将列 total_etnicities
放在一个单独的系列中,并且只有在需要报告结果时才会我把它们组合起来
如果您确实希望将此结果作为 df
中的额外列,您可以通过以下方式实现:
df = df.join(result, on='tconst')
执行此操作的最佳方法是将所有列与给定列进行比较,因为基尼系数定义了分布的差异。您将生成比较分布的基尼系数,例如意大利、法国、犹太人。然后,与给定的列进行比较,您甚至可以将这些种族分组为相似分布的集群。
假设 df2 是您的数据框。基尼指数公式为:
您 select Pandas 中的数据透视列 (place_y):
place_y=df2.columns.get_loc("price_doc")
gini=[]
for i in range(0,df2.shape[1]):
gini.append((df2.shape[0]+1-2*(np.sum((df2.shape[0]+1-df2.ix[:,i])*df2.ix[:,place_y])/np.sum(df2.ix[:,place_y])))/df2.shape[0])
然后你 select 最符合你的阈值的列,假设 0.2,最相似的分布:
np.where(np.array(np.abs(gini))<.2)[0]
在您的情况下,您似乎想要比较示例(行)而不是特征(列)以生成新列。这是相同的理性,换位。在您的数据透视行中,基尼系数将为零,而所有其他行都有其系数。