熊猫 groupby 没有将按列分组转换为索引

Posted

技术标签:

【中文标题】熊猫 groupby 没有将按列分组转换为索引【英文标题】:pandas groupby without turning grouped by column into index 【发布时间】:2015-11-10 14:55:33 【问题描述】:

pandas groupby 的默认行为是将 group by 列转换为索引,并将它们从数据框的列列表中删除。例如,假设我有一个包含这些列的数据框

col1|col2|col3|col4

如果我以这种方式应用 groupby 列 col2col3

df.groupby(['col2','col3']).sum()

数据框df 的列列表中不再有['col2','col3']。它们会自动变成结果数据帧的索引。

我的问题是如何对列执行 groupby 并将该列保留在数据框中?

【问题讨论】:

【参考方案1】:
df.groupby(['col2','col3'], as_index=False).sum()

【讨论】:

df.groupby(['col2','col3'], as_index=False).sum() 对我不起作用。我在第 2 行有我的旧列(c1、c2、c3、c4)和我的新列(c5、c6)作为标题,但希望 c1-c6 都是标题。 它会从新生成的 df 中删除“col2”和“col3”,所以这不是问题的答案,而是“Boudewijn Aasman 的答案是?”【参考方案2】:

另一种方法是:

df.groupby(['col2', 'col3']).sum().reset_index()

【讨论】:

【参考方案3】:

不确定,但我认为正确的答案是

df.groupby(['col2','col3']).sum()
df = df.reset_index()

至少我一直在做的是避免使用多索引的数据帧。

【讨论】:

这与半年前发布的上述解决方案完全相同。只是没有链接。 是与否,也与问题相似,与接受答案的区别在于 as_index=False 与 .reset_index(),通常相同但并非总是 ***.com/a/51933722/1598953。虽然我不记得为什么我的旧自我发布它,但我认为接受的答案对他不起作用。 对不起,我的意思是 Boudewijn Aasman 的回答。那个是相同的df.groupby(['col2', 'col3']).sum().reset_index()【参考方案4】:

添加了以下有点详细的答案,以帮助那些仍然对使用哪种答案变体感到困惑的人。

首先,针对这个问题,建议的两种解决方案是:

解决方案 1df.groupby(['col2', 'col3'], as_index=False).sum() 解决方案 2df.groupby(['col2', 'col3']).sum().reset_index()

两者都给出了预期的结果。


解决方案一:

如文档中所述,as_index 将要求 SQL 样式 分组输出,这将有效地要求 pandas 在输出中保留这些按列分组的内容准备好了。

as_index:布尔型,默认为真

对于聚合输出,返回以组标签为索引的对象。 仅与 DataFrame 输入相关。 as_index=False 是有效的 “SQL 风格” 分组输出。

例子:

给定以下数据框:

  col1  col2      col3      col4
0    A     1  0.502130  0.959404
1    A     3  0.335416  0.087215
2    B     2  0.067308  0.084595
3    B     4  0.454158  0.723124
4    B     4  0.323326  0.895858
5    C     2  0.672375  0.356736
6    C     5  0.929655  0.371913
7    D     5  0.212634  0.540736
8    D     5  0.471418  0.268270
9    E     1  0.061270  0.739610

应用第一个解决方案给出:

>>> df.groupby(["col1", "col2"], as_index=False).sum()

  col1  col2      col3      col4
0    A     1  0.502130  0.959404
1    A     3  0.335416  0.087215
2    B     2  0.067308  0.084595
3    B     4  0.777483  1.618982
4    C     2  0.672375  0.356736
5    C     5  0.929655  0.371913
6    D     5  0.684052  0.809006
7    E     1  0.061270  0.739610

正确保留 groupby 列的位置。


解决方案 2:

要理解第二种解决方案,让我们看一下前面命令的输出as_index = True,这是pandas.DataFrame.groupby的默认行为(检查documentation):

>>> df.groupby(["col1", "col2"], as_index=True).sum()
               col3      col4
col1 col2                    
A    1     0.502130  0.959404
     3     0.335416  0.087215
B    2     0.067308  0.084595
     4     0.777483  1.618982
C    2     0.672375  0.356736
     5     0.929655  0.371913
D    5     0.684052  0.809006
E    1     0.061270  0.739610

如您所见,groupby 键成为数据帧的索引。使用pandas.DataFrame.reset_index(检查documentation),我们可以将数据帧的索引作为列放回并使用默认索引。这也使我们得到与上一步相同的结果:

>>> df.groupby(['col1', 'col2']).sum().reset_index()
  col1  col2      col3      col4
0    A     1  0.502130  0.959404
1    A     3  0.335416  0.087215
2    B     2  0.067308  0.084595
3    B     4  0.777483  1.618982
4    C     2  0.672375  0.356736
5    C     5  0.929655  0.371913
6    D     5  0.684052  0.809006
7    E     1  0.061270  0.739610

基准测试

请注意,由于第一个解决方案在 1 步中实现了要求,而在第二个解决方案中是 2 个步骤,因此前者稍微快一些:

%timeit df.groupby(["col1", "col2"], as_index=False).sum()
3.38 ms ± 21.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df.groupby(["col1", "col2"]).sum().reset_index()
3.9 ms ± 365 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

【讨论】:

使用 as_index=False 创建的数据框(此处为解决方案 1)不包含为分组指定的列(col1 col2 在您的示例中)。因此解决方案 1 本身不是一个有效的答案。

以上是关于熊猫 groupby 没有将按列分组转换为索引的主要内容,如果未能解决你的问题,请参考以下文章

熊猫数据框按列位置分组

如何对两个字段进行分组并将索引设置为两个字段之一。熊猫,Python-3

如果列表中的索引,熊猫按功能分组以执行不同的方法

为熊猫箱线图(groupby)设置无标题

将熊猫中的数据分组[重复]

listagg - 多个按列分组