如何对多列进行分组并求最后一列的总和?

3

我有一个一直在尝试解决的问题:

我希望代码能够基于最频繁的数字对这个数据框的多个列进行分组,并对最后一列的值求和。例如:

df = pd.DataFrame({'A':[1000, 1000, 1000, 1000, 1000, 200, 200, 500, 500],
                   'B':[380, 380, 270, 270, 270, 45, 45, 45, 55],
                   'C':[380, 380, 270, 270, 270, 88, 88, 88, 88],
                   'D':[45, 32, 67, 89, 51, 90, 90, 90, 90]})

df

       A     B     C    D
0   1000   380   380   45
1   1000   380   380   32
2   1000   270   270   67
3   1000   270   270   89
4   1000   270   270   51
5    200    45    88   90
6    200    45    88   90
7    500    45    88   90
8    500    55    88   90

我希望代码能够展示以下结果:
       A     B     C    D
0   1000   380   380   284
1   1000   380   380   284
2   1000   270   270   284
3   1000   270   270   284
4   1000   270   270   284
5    200    45    88   360
6    200    45    88   360
7    500    45    88   360
8    500    55    88   360


注意到第一行中最常见的值为1000,因此我对“A”列进行分组,这样在“D”列中得到总和为284。然而,在最后一行中,最常见的数字是88,不在“A”列中,而在“C”列中。我尝试通过按“C”列分组来汇总“D”列的值,并获得360。我不确定自己是否表达清楚。
我尝试使用函数df['D'] = df.groupby(['A', 'B', 'C'])['D'].transform('sum'),但它没有显示上述所需的结果。
有没有一种类似pandas样式的解决方法?先感谢您!

你如何决定停止考虑一个频繁出现的值?仅仅看你的例子中的数据,1000是最频繁出现的值。此外,频繁出现的值可能不是连续的,就像你的例子一样。你可以使用mode函数,但它会返回与你期望的结果不同的结果。 - Carlos Melus
1
df['D'] = df.groupby(['A', 'B', 'C'])['D'].sum() - Prayson W. Daniel
@CarlosMelus 当一个值在下一行不再出现时,我会停止考虑它作为一个频繁值。 - Matheus Soares
@PraysonW.Daniel 没有成功!代码显示了一个错误... - Matheus Soares
你收到了什么错误信息? - Prayson W. Daniel
@PraysonW.Daniel 我遇到了这个错误 "TypeError: incompatible index of inserted column with frame index",很有趣的是因为这段代码 df['D'] = df.groupby(['A', 'B', 'C'])['D'].transform('sum') 没有报错。 - Matheus Soares
1个回答

3

代码

def get_count_sum(col, func):
    return df.groupby(col).D.transform(func)
    
ga = get_count_sum('A', 'count')
gb = get_count_sum('B', 'count')
gc = get_count_sum('C', 'count')


conditions = [
    ((ga > gb) & (ga > gc)),
    ((gb > ga) & (gb > gc)),
    ((gc > ga) & (gc > gb)),
]

choices = [get_count_sum('A', 'sum'), 
           get_count_sum('B', 'sum'),
           get_count_sum('C', 'sum')]

df['D'] = np.select(conditions, choices)
df

输出

    A       B   C   D
0   1000    380 380 284
1   1000    380 380 284
2   1000    270 270 284
3   1000    270 270 284
4   1000    270 270 284
5   200     45  88  360
6   200     45  88  360
7   500     45  88  360
8   500     55  88  360

解释

  1. 由于我们需要按照每个列'A', 'B'或'C'进行分组,考虑哪个列具有最大的重复数字,因此首先我们在三个列中检查最大的重复数字,并将groupby输出存储在A,B,C列的ga,gb和gc中。

  2. 我们正在检查条件中哪列的频繁数字最大。

  3. 根据条件,我们正在应用if else条件的选择。

  4. np.select就像if-elif-else,其中我们将条件和所需的输出放置在选择中。


多么出色的解决方案!非常感谢! - Matheus Soares

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接