熊猫:条件组特定计算

时间:2014-06-16 19:32:28

标签: python pandas

假设我有一个带密钥的表(例如客户ID)和两个数字列C1和C2。我想按键(客户)对行进行分组,并在其列上运行一些聚合器,如sum和mean。在计算组聚合器之后,我想将结果分配回DataFrame中的每个客户行(因为某些客户范围的功能已添加到每一行)。

我可以看到我可以做类似的事情 df['F1'] = df.groupby(['Key'])['C1'].transform(np.sum)
如果我只想聚合一列,并能够将结果添加回DataFrame。

我是否可以将其设置为条件 - 我是否可以仅在C2列等于某个数字X的行中添加C1列,并且仍能将结果添加回DataFrame?

如何在以下行的组合上运行聚合器:
np.sum(C1 + C2)?

实施它的最简单,最优雅的方法是什么?最有效的方法是什么?这些聚合可以在一条路径上完成吗?

提前谢谢。

2 个答案:

答案 0 :(得分:5)

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

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,只需将数据帧传递给.groubpy即可。例如,如果C2小于8或大于9,则希望组总和为“C1”。

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=['']))

答案 1 :(得分:0)

我发现另一种使用apply()而不是transform()的方法,但你需要将结果表与输入DataFrame连接起来,我还没想出怎么做。非常感谢帮助完成加入零件或任何更好的替代品的表格。

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 ...
#

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 ... #