在列*和*索引上使用 groupby 并与 pandas 数据框聚合
Posted
技术标签:
【中文标题】在列*和*索引上使用 groupby 并与 pandas 数据框聚合【英文标题】:Use groupby and aggregate with pandas dataframe on columns *and* index 【发布时间】:2020-11-22 01:39:28 【问题描述】:我有一个与此类似的表,在 (A, B) 上有一个多索引
>>> columns = ["A", "B", "C", "D"]
... data = [
... [1, 1, 99, 22],
... [1, 2, 87, 24],
... [1, 3, 65, 31],
... [2, 1, 88, 30],
... [2, 2, 76, 33],
... [2, 3, 23, 32],
... [2, 4, 38, 28],
... [3, 1, 33, 40],
... [3, 2, 23, 41],
...]
>>>
>>> pd_table = pd.DataFrame(data=data, columns=columns)
>>> pd_table.set_index(["A", "B"], inplace=True)
>>> print(pd_table)
C D
A B
1 1 99 22
2 87 24
3 65 31
2 1 88 30
2 76 33
3 23 32
4 38 28
3 1 33 40
2 23 41
如果我想对索引上的结果进行分组,并在组上应用聚合函数,我可以这样做
>>> roll_table = pd_table.groupby("A").aggregate("C": min, "D": max)
>>> print(roll_table)
C D
A
1 65 31
2 23 33
3 23 41
但是,这会降低我想保留的 B 索引。我也想对这个专栏应用一个函数,但显然这失败了:
>>> roll_table = pd_table.groupby("A").aggregate("B": max, "C": min, "D": max)
>>> print(roll_index)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "...\Python\Python38\site-packages\pandas\core\groupby\generic.py", line 928, in aggregate
result, how = self._aggregate(func, *args, **kwargs)
File "...\Python\Python38\site-packages\pandas\core\base.py", line 357, in _aggregate
raise SpecificationError("nested renamer is not supported")
pandas.core.base.SpecificationError: nested renamer is not supported
解决这个问题的一种方法是将 B 索引移动到列,执行聚合,然后将其移回索引,但这似乎很麻烦:
>>> roll_table = pd_table.reset_index(level="B")
>>> roll_table = roll_table.groupby("A").aggregate("B": max, "C": min, "D": max)
>>> roll_table = roll_table.set_index("B", append=True)
>>> print(roll_table)
C D
A B
1 3 65 31
2 4 23 33
3 2 23 41
有没有办法在未分组的索引上也进行聚合?
举一个用例示例,索引可能是坐标,我想使用第一个 y 值作为参考点。或者我可能想使用"size"
来跟踪有多少值组合在一起。
>>> columns = ["x", "y", "Pressure"]
>>> data = [
... [ 1, 1, 99],
... [ 1, 2, 98],
... [ 1, 3, 101],
... [ 2, 2, 100],
... [ 2, 3, 96],
... [ 3, 1, 100],
... [ 3, 2, 102],
... [ 3, 3, 100],
... ]
>>>
>>> pd_table = pd.DataFrame(data=data, columns=columns)
>>> pd_table.set_index(["x", "y"], inplace=True)
>>>
>>> pd_table.reset_index(level="y", inplace=True)
>>> roll_index = pd_table.groupby("x").aggregate("y": "first", "Pressure": "mean")
>>> roll_index.set_index("y", append=True, inplace=True)
>>>
>>> print(roll_index)
Pressure
x y
1 1 99.333333
2 2 98.000000
3 1 100.666667
【问题讨论】:
如何获得“B”的值,因为B
处的索引对于C
和D
的第2 行会有所不同?除非您确定所有组的C
的最小值和D
的最大值将在同一行,否则B
听起来不可能。
@sammywemmy 我想对分组的B
索引应用聚合函数。在我的示例中,这是"B": max, ...
部分。它不必与C
或D
中的任何值对应,也不必是max
函数,它可以是avg
或first
。
pd.Grouper()
允许您指定 MultiIndex 的级别,因此您可以按索引级别和列进行聚合;熊猫文档在这里:pandas.pydata.org/pandas-docs/stable/user_guide/…
@jsmart,请分享一个例子,以便我们向你学习。
【参考方案1】:
这是获得结果的一种选择:
pd.DataFrame(key : "B":value.index.get_level_values('B').max(),
"C":value.C.min(),
"D":value.D.max()
for key, value in pd_table.groupby("A").__iter__()).T
B C D
1 3 65 31
2 4 23 33
3 2 23 41
【讨论】:
以上是关于在列*和*索引上使用 groupby 并与 pandas 数据框聚合的主要内容,如果未能解决你的问题,请参考以下文章