对于熊猫 >= 0.25
命名返回的聚合列的功能已在 master 分支中重新引入,并针对 pandas 0.25。新语法是.agg(new_col_name=('col_name', 'agg_func')
. 来自上面链接的 PR 的详细示例:
In [2]: df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
...: 'height': [9.1, 6.0, 9.5, 34.0],
...: 'weight': [7.9, 7.5, 9.9, 198.0]})
...:
In [3]: df
Out[3]:
kind height weight
0 cat 9.1 7.9
1 dog 6.0 7.5
2 cat 9.5 9.9
3 dog 34.0 198.0
In [4]: df.groupby('kind').agg(min_height=('height', 'min'),
max_weight=('weight', 'max'))
Out[4]:
min_height max_weight
kind
cat 9.1 9.9
dog 6.0 198.0
根据此 PR,还可以使用此语法和我之前建议的两步重命名语法(如下)使用多个 lambda 表达式。同样,从 PR 中的示例复制:
In [2]: df = pd.DataFrame({"A": ['a', 'a'], 'B': [1, 2], 'C': [3, 4]})
In [3]: df.groupby("A").agg({'B': [lambda x: 0, lambda x: 1]})
Out[3]:
B
<lambda> <lambda 1>
A
a 0 1
然后.rename()
,或一口气:
In [4]: df.groupby("A").agg(b=('B', lambda x: 0), c=('B', lambda x: 1))
Out[4]:
b c
A
a 0 0
对于熊猫 < 0.25
unutbu 描述的当前接受的答案是在熊猫版本 <= 0.20 中执行此操作的好方法。但是,从 pandas 0.20 开始,使用此方法会引发警告,指出该语法在 pandas 的未来版本中将不可用。
系列:
FutureWarning:不推荐在 Series 上使用 dict 进行聚合,并将在未来版本中删除
数据框:
FutureWarning:不推荐使用带有重命名的字典,并将在未来的版本中删除
根据pandas 0.20 changelog,在聚合时重命名列的推荐方法如下。
# Create a sample data frame
df = pd.DataFrame({'A': [1, 1, 1, 2, 2],
'B': range(5),
'C': range(5)})
# ==== SINGLE COLUMN (SERIES) ====
# Syntax soon to be deprecated
df.groupby('A').B.agg({'foo': 'count'})
# Recommended replacement syntax
df.groupby('A').B.agg(['count']).rename(columns={'count': 'foo'})
# ==== MULTI COLUMN ====
# Syntax soon to be deprecated
df.groupby('A').agg({'B': {'foo': 'sum'}, 'C': {'bar': 'min'}})
# Recommended replacement syntax
df.groupby('A').agg({'B': 'sum', 'C': 'min'}).rename(columns={'B': 'foo', 'C': 'bar'})
# As the recommended syntax is more verbose, parentheses can
# be used to introduce line breaks and increase readability
(df.groupby('A')
.agg({'B': 'sum', 'C': 'min'})
.rename(columns={'B': 'foo', 'C': 'bar'})
)
有关更多详细信息,请参阅0.20 变更日志。
更新 2017-01-03 以回应 @JunkMechanic 的评论。
使用旧式字典语法,可以将多个lambda
函数传递给.agg
,因为这些函数将使用传递字典中的键重命名:
>>> df.groupby('A').agg({'B': {'min': lambda x: x.min(), 'max': lambda x: x.max()}})
B
max min
A
1 2 0
2 4 3
多个函数也可以作为列表传递给单个列:
>>> df.groupby('A').agg({'B': [np.min, np.max]})
B
amin amax
A
1 0 2
2 3 4
但是,这不适用于 lambda 函数,因为它们是匿名的并且都是 return <lambda>
,这会导致名称冲突:
>>> df.groupby('A').agg({'B': [lambda x: x.min(), lambda x: x.max]})
SpecificationError: Function names must be unique, found multiple named <lambda>
为了避免SpecificationError
, 命名函数可以先验定义而不是使用lambda
. 合适的函数名也可以避免之后调用.rename
数据框。可以使用与上述相同的列表语法传递这些函数:
>>> def my_min(x):
>>> return x.min()
>>> def my_max(x):
>>> return x.max()
>>> df.groupby('A').agg({'B': [my_min, my_max]})
B
my_min my_max
A
1 0 2
2 3 4