【问题标题】:Python - Pandas Data manipulation to calculate Gini CoefficientPython - Pandas 数据操作来计算基尼系数
【发布时间】:2018-07-11 14:46:02
【问题描述】:

我有如下形状的数据集:

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]

【问题讨论】:

  • 我们能否看到上述数据的预期输出。
  • @Dark 我编辑了,希望清楚。谢谢

标签: python python-3.x pandas data-science


【解决方案1】:

您可以在此处使用 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

【讨论】:

  • 我得到这个 ZeroDivisionError: long 除法或模数为零
  • 你用的是python 2吗??
  • 是的,我使用的是 Python 2。
【解决方案2】:
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')

【讨论】:

  • 如果将最后一行放在 df["diversity"] 中,则在所有值中获取 NaN
  • 使用 .values 并等同于列
【解决方案3】:

最好的方法是将所有列与给定的列进行比较,因为基尼系数定义了分布的差异。您将生成比较分布的基尼系数,例如意大利语、法语、犹太人。然后,与给定的列进行比较,您甚至可以将这些种族分组到相似分布的集群中。

假设 df2 是您的数据框。基尼指数公式为:

在 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])

然后您选择最符合您的阈值的列,假设 0.2,最相似的分布:

np.where(np.array(np.abs(gini))<.2)[0]

在您的情况下,您似乎想比较示例(行)而不是特征(列)以生成新列。这是同样的理性,换位了。在您的枢轴行中,基尼系数将为零,所有其他人都有自己的系数。

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 2017-01-23
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 2019-11-08
    • 2016-09-23
    • 1970-01-01
    • 2018-04-02
    相关资源
    最近更新 更多