Pandas:条件分组特定计算

5 投票
2 回答
6448 浏览
提问于 2025-04-18 09:59

假设我有一个表格,里面有一个关键字段(比如客户ID)和两个数字列C1和C2。我想根据这个关键字段(客户)来分组这些行,然后对这些列进行一些汇总,比如求和和平均值。计算完分组汇总后,我想把结果再加回到每个客户的行中,作为一些客户的特征。

我可以这样做:
df['F1'] = df.groupby(['Key'])['C1'].transform(np.sum)
如果我只想对一列进行汇总,并且能够把结果加回到数据框中,这样是可以的。

那么我能不能设置条件呢?比如我只想对C2列等于某个数字X的行进行C1列的求和,并且还能把结果加回到数据框中?

我该如何对一组行进行汇总,比如:
np.sum(C1 + C2)?

实现这个功能最简单、最优雅的方法是什么?最有效率的方法又是什么?这些汇总能不能在一个步骤中完成?

谢谢大家的帮助。

2 个回答

1

我找到了一种不同的方法,它使用apply()而不是transform(),不过你需要把结果表和输入的数据表连接起来,我还没弄明白怎么做。希望能有人帮我完成这个连接表的部分,或者给我一些更好的建议。

df = pd.DataFrame({'Key': ['a','a','b','b','c','c'],
                            'C1': [1,2,3,4,5,6],
                            'C2': [7,8,9,10,11,12]})

# Group g will be given as a DataFrame
def group_feature_extractor(g):
    feature_1 = (g['C1'] + g['C2']).sum()

    even_C1_filter = g['C1'] % 2 == 0
    feature_2 = g[even_C1_filter]['C2'].sum()

    return pd.Series([feature_1, feature_2], index = ['F1', 'F2'])

# Group once
group = df.groupby(['Key'])

# Extract features from each group
group_features = group.apply(group_feature_extractor)

#
# Join with the input data frame ...
#

6

这里是一些虚拟数据的设置。

In [81]: df = pd.DataFrame({'Key': ['a','a','b','b','c','c'], 
                            'C1': [1,2,3,4,5,6],  
                            'C2': [7,8,9,10,11,12]})
In [82]: df['F1'] = df.groupby('Key')['C1'].transform(np.sum)

In [83]: df
Out[83]: 
   C1  C2 Key  F1
0   1   7   a   3
1   2   8   a   3
2   3   9   b   7
3   4  10   b   7
4   5  11   c  11
5   6  12   c  11

如果你想要进行条件分组,可以在传递给 .groupby 的时候先过滤一下数据框。例如,如果你想要计算 'C1' 的组总和,但只在 'C2' 小于 8 或大于 9 的情况下。

In [87]: cond = (df['C2'] < 8) | (df['C2'] > 9)

In [88]: df['F2'] = df[cond].groupby('Key')['C1'].transform(np.sum)

In [89]: df
Out[89]: 
   C1  C2 Key  F1  F2
0   1   7   a   3   1
1   2   8   a   3 NaN
2   3   9   b   7 NaN
3   4  10   b   7   4
4   5  11   c  11  11
5   6  12   c  11  11

这样做是可行的,因为 transform 操作会保留索引,所以它仍然会和原始数据框正确对齐。

如果你想要对两个列的组总和进行求和,可能这样做会比较简单?也许有人有更聪明的方法。

In [93]: gb = df.groupby('Key')

In [94]: df['C1+C2'] = gb['C1'].transform(np.sum) + gb['C2'].transform(np.sum)

编辑:还有一种方法可以获取多个列的组总和。语法上并没有更简洁,但对于很多列来说可能会更方便。

df['C1_C2'] = gb[['C1','C2']].apply(lambda x: pd.DataFrame(x.sum().sum(), index=x.index, columns=['']))

撰写回答