Pandas 使用动态列名聚合
Posted
技术标签:
【中文标题】Pandas 使用动态列名聚合【英文标题】:Pandas aggregate with dynamic column names 【发布时间】:2020-01-19 12:01:27 【问题描述】:我有一个脚本可以生成一个带有不同数量值列的 pandas 数据框。例如,这个 df 可能是
import pandas as pd
df = pd.DataFrame(
'group': ['A', 'A', 'A', 'B', 'B'],
'group_color' : ['green', 'green', 'green', 'blue', 'blue'],
'val1': [5, 2, 3, 4, 5],
'val2' : [4, 2, 8, 5, 7]
)
group group_color val1 val2
0 A green 5 4
1 A green 2 2
2 A green 3 8
3 B blue 4 5
4 B blue 5 7
我的目标是获取每个值列的分组平均值。在这种特定情况下(有 2 个值列),我可以使用
df.groupby('group').agg("group_color": "first", "val1": "mean", "val2": "mean")
group_color val1 val2
group
A green 3.333333 4.666667
B blue 4.500000 6.000000
但当相关数据框具有更多值列(val3、val4 等)时,这不起作用。 有没有办法动态取“所有其他列”或“名称中包含 val 的所有列”的平均值?
【问题讨论】:
一组的 group_color 是否总是相同的? @QuangHoang:是的,是这样,但我还是想保留它 【参考方案1】:比较简单
df.groupby('group').agg(lambda x : x.head(1) if x.dtype=='object' else x.mean())
Out[63]:
group_color val1 val2
group
A green 3.333333 4.666667
B blue 4.500000 6.000000
【讨论】:
不错的解决方案!你能解释一下为什么非数字列的 dtype 是 object 吗? @MartijnVanAttekum 这是熊猫、字符串和其他都归类为对象的数据类型【参考方案2】:如果您的group_color
在一组中始终相同,您可以这样做:
df.pivot_table(index=['group','group_color'],aggfunc='mean')
输出:
val1 val2
group group_color
A green 3.333333 4.666667
B blue 4.500000 6.000000
在另一种情况下,您可以构建字典并将其传递给agg
:
agg_dict = f: 'first' if f=='group_color' else 'mean' for f in df.columns[1:]
df.groupby('group').agg(agg_dict)
哪个输出:
group_color val1 val2
group
A green 3.333333 4.666667
B blue 4.500000 6.000000
【讨论】:
你是pivot_table
答案是正确的。我使用了几乎相同的东西,但添加了reset_index
。【参考方案3】:
不幸的是,您将不得不分别应用这两个聚合函数(或者重复 "valn": "mean"
与 valx
列一样多次)。 Groupby.agg
可以使用字典,但键必须是单独的列。
我这样做的方法是使用DataFrame.filter
选择数据帧的子集,其中列遵循valx
的格式,用平均值聚合,然后用聚合结果分配新列列:
(df.filter(regex=r'^val').groupby(df.group).mean()
.assign(color = df.group_color.groupby(df.group).first()))
val1 val2 color
group
A 3.333333 4.666667 green
B 4.500000 6.000000 blue
【讨论】:
【参考方案4】:根据 OP 的评论
我们可以同时按'group'
和'group_color'
进行分组,而不会有每个'group'
有多个唯一'group_color'
的风险
因此:
df.groupby(['group', 'group_color']).mean().reset_index(level=1)
group_color val1 val2
group
A green 3.333333 4.666667
B blue 4.500000 6.000000
【讨论】:
【参考方案5】:您可以使用 2 个可以像这样组合的词典:
df.groupby('group').agg(**'group_color': 'first', **c: 'mean' for c in df.columns if c.startswith('val'))
在这种情况下,您有一个 dict
具有固定聚合,另一个具有动态列选择。
【讨论】:
以上是关于Pandas 使用动态列名聚合的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 动态行转列(参数化表名分组列行转列字段字段值)