Pandas 按 groupby 求和,但不包括某些列

Posted

技术标签:

【中文标题】Pandas 按 groupby 求和,但不包括某些列【英文标题】:Pandas sum by groupby, but exclude certain columns 【发布时间】:2015-12-21 11:01:16 【问题描述】:

在 Pandas 数据框上执行 groupby 的最佳方法是什么,但从该 groupby 中排除某些列?例如我有以下数据框:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          Wheat   5312        Ha      10       20      30
2      Afghanistan  25          Maize   5312        Ha      10       20      30
4      Angola       15          Wheat   7312        Ha      30       40      50
4      Angola       25          Maize   7312        Ha      30       40      50

我想按 Country 和 Item_Code 列分组,只计算 Y1961、Y1962 和 Y1963 列下的行的总和。生成的数据框应如下所示:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          C3      5312        Ha      20       40       60
4      Angola       25          C4      7312        Ha      60       80      100

现在我正在这样做:

df.groupby('Country').sum()

但是,这也会将 Item_Code 列中的值相加。有什么方法可以指定 sum() 操作中包含哪些列以及排除哪些列?

【问题讨论】:

【参考方案1】:

如果您正在寻找一种更通用的方法来应用到许多列,您可以做的是构建一个列名列表并将其作为分组数据框的索引传递。在你的情况下,例如:

columns = ['Y'+str(i) for year in range(1967, 2011)]

df.groupby('Country')[columns].agg('sum')

【讨论】:

【参考方案2】:

您可以选择 groupby 的列:

In [11]: df.groupby(['Country', 'Item_Code'])[["Y1961", "Y1962", "Y1963"]].sum()
Out[11]:
                       Y1961  Y1962  Y1963
Country     Item_Code
Afghanistan 15            10     20     30
            25            10     20     30
Angola      15            30     40     50
            25            30     40     50

请注意,传递的列表必须是列的子集,否则您将看到 KeyError。

【讨论】:

如何将每个国家和项目代码的记录计数作为另一列包含在内? 您可以在分组之前创建一个虚拟列,该列仅包含 1。然后 sum 会将这些汇总起来创建一个计数。 如果您只想排除一两列,那么您将获得所有列名称,如 listColumns = list(df.columns) 然后删除您不想要的列 listColumns.remove('Y1964') 最后进行求和:df.groupby(['Country', 'Item_Code'])[listColumns].sum() 非常感谢。我可以让 groupby 工作,但不能让选择部分工作。我放入的列列表在数据框中,但它不断提高 ValueError:cannot reindex from a duplicate axis @BowenLiu 如果您有多个具有相同名称的列,则会显示此错误。在这种情况下,您必须使用 iloc to 或 loc 来获取所需的列,我认为您必须在 groupby 之前这样做。【参考方案3】:

agg 函数将为您执行此操作。将列和函数作为带有列的 dict 传递,输出:

df.groupby(['Country', 'Item_Code']).agg('Y1961': np.sum, 'Y1962': [np.sum, np.mean])  # Added example for two output columns from a single input column

这将只显示分组列和指定的聚合列。在这个例子中,我包含了两个应用于“Y1962”的聚合函数。

要准确获得您希望看到的内容,请将其他列包含在 group by 中,并将总和应用于框架中的 Y 变量:

df.groupby(['Code', 'Country', 'Item_Code', 'Item', 'Ele_Code', 'Unit']).agg('Y1961': np.sum, 'Y1962': np.sum, 'Y1963': np.sum)

【讨论】:

谢谢,这可以概括吗?我有很多 Y1961 形式的列...所以我生成了一个这样的列表:yrs = ['Y' + str(x) for x in range(1961, 2010 + 1, 1)]。您的解决方案可以在 agg 中使用“yrs”吗? 我真的很喜欢这个主意。诀窍是构造这个dict,其值为numpy sum 函数。相反,如果您只想对所有剩余的列求和,那么如果所有 group by 列都包含在 group by 语句中,那么您的原始解决方案将起作用。

以上是关于Pandas 按 groupby 求和,但不包括某些列的主要内容,如果未能解决你的问题,请参考以下文章

Pandas DataFrame groupby,跨列计数和求和

数据分析—Pandas 中的分组聚合Groupby 高阶操作

pandas groupby 可以聚合成一个列表,而不是 sum、mean 等吗?

pandas取列值转化为列表

Groupby对python中的多列求和并计数

熊猫:将汇率查询乘以另一个数据框的相同日期后,按每日金额求和和汇总