具有多索引列的 Pandas groupby
Posted
技术标签:
【中文标题】具有多索引列的 Pandas groupby【英文标题】:Pandas groupby with multiindex columns 【发布时间】:2021-07-13 11:34:38 【问题描述】:我的目标,我期望实现它的方式,以及会发生什么
我正在尝试在具有多索引列的 DataFrame 上执行 groupby,该列使用 Series(不带多索引)作为分组依据的输入。具体来说,给定以下 DataFrame
>>> df
X Y
A B C A B C
2020-01-01 9 1 2 1 6 5
2020-01-02 5 7 8 0 6 9
2020-01-03 6 3 4 8 6 1
2020-01-06 0 0 9 0 5 1
2020-01-07 8 7 4 8 3 1
以及代表组的系列
>>> groups
A D
B D
C E
dtype: object
我尝试运行以下命令
>>> df.groupby(groups, axis=1, level=1).sum()
并期望得到
X Y
D E D E
2020-01-01 10 2 7 5
2020-01-02 12 8 6 9
2020-01-03 9 4 14 1
2020-01-06 0 9 5 1
2020-01-07 15 4 11 1
但是我得到以下错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/frame.py", line 6717, in groupby
return DataFrameGroupBy(
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/groupby/groupby.py", line 560, in __init__
grouper, exclusions, obj = get_grouper(
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/groupby/grouper.py", line 828, in get_grouper
Grouping(
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/groupby/grouper.py", line 485, in __init__
) = index._get_grouper_for_level(self.grouper, level)
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/indexes/multi.py", line 1487, in _get_grouper_for_level
grouper = level_values.map(mapper)
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/indexes/base.py", line 5098, in map
new_values = super()._map_values(mapper, na_action=na_action)
File "/home/zak/anaconda3/envs/lib/python3.8/site-packages/pandas/core/base.py", line 937, in _map_values
new_values = map_f(values, mapper)
File "pandas/_libs/lib.pyx", line 2467, in pandas._libs.lib.map_infer
TypeError: 'numpy.ndarray' object is not callable
我正在使用 Python 3.8.8 和 Pandas 1.2.3 版。
次优解决方案
我发现实现上述目标的一种方法是使用以下代码,但我特别想知道是否有更简洁的方法可以做到这一点。如果不是,为什么不呢?对我来说,上述尝试是 groupby 方法的预期行为,但似乎我误解了它背后的逻辑。
>>> df, groups = df.align(groups, axis=1, level=1)
>>> df.groupby(groups, axis=1).apply(lambda x: x.sum(axis=1, level=0)).swaplevel(axis=1).sort_index(axis=1)
X Y
D E D E
2020-01-01 10 2 7 5
2020-01-02 12 8 6 9
2020-01-03 9 4 14 1
2020-01-06 0 9 5 1
2020-01-07 15 4 11 1
【问题讨论】:
【参考方案1】:您可以在MultiIndex
的第二级使用rename
,然后按两个级别聚合:
df = df.rename(columns=groups, level=1).sum(axis=1, level=[0,1])
#working like
#df = df.rename(columns=groups, level=1).groupby(axis=1, level=[0,1]).sum()
print (df)
X Y
D E D E
2020-01-01 10 2 7 5
2020-01-02 12 8 6 9
2020-01-03 9 4 14 1
2020-01-06 0 9 5 1
2020-01-07 15 4 11 1
你的解决方案应该被 lambda 函数改变,但输出不同:
df = df.groupby(lambda x: groups[x], axis=1, level=1).sum()
print (df)
D E
2020-01-01 17 7
2020-01-02 18 17
2020-01-03 23 5
2020-01-06 5 10
2020-01-07 26 5
【讨论】:
我会接受答案,因为它是迄今为止唯一的答案,而且比我的尝试要干净得多。但是,我仍然对为什么这个简单的操作必须涉及重命名列等复杂的解决方案感到困惑?对我来说,这似乎应该是一个简单的日常操作。 @ZakTurcinovic - 很难回答的问题,对于 pandas 开发人员来说可能更多。以上是关于具有多索引列的 Pandas groupby的主要内容,如果未能解决你的问题,请参考以下文章