Pandas数据清洗遇阻:如何创建基于行值的活动合计列?
解决基于特定行列值创建合计列的问题
嘿,我来帮你搞定这个数据清洗的难题!你想要的是按CustomerID分组,统计每个客户的Email和Call总次数,然后把这些统计值对应到每一行的新列里,对吧?
先说说你之前代码的问题:你写的df.groupby('ActivityType'=='Email').transform('sum')逻辑不对——'ActivityType'=='Email'是一个布尔值(结果是False),不是用来分组的列名,而且你需要按CustomerID分组,而不是按ActivityType的判断结果来分组,自然得不到想要的结果。
下面给你两种可行的解决方案:
方法一:用transform结合条件统计
这种方法最直接,直接在原DataFrame上生成合计列:
import pandas as pd # 你的原始数据 df = pd.DataFrame({ 'CustomerID': ['01134A', '01134B', '01134A', '01134B'], 'ActivityType': ['Email', 'Email', 'Call', 'Email'] }) # 生成TotalEmail列:按CustomerID分组,统计每组内Email的数量 df['TotalEmail'] = df.groupby('CustomerID')['ActivityType'].transform(lambda x: (x == 'Email').sum()) # 生成TotalCall列:同理统计Call的数量 df['TotalCall'] = df.groupby('CustomerID')['ActivityType'].transform(lambda x: (x == 'Call').sum()) print(df)
运行后就能得到你期望的输出:
CustomerID ActivityType TotalEmail TotalCall 0 01134A Email 1 1 1 01134B Email 2 0 2 01134A Call 1 1 3 01134B Email 2 0
代码解释:
groupby('CustomerID'):把数据按客户ID分成不同的组transform():会把每个组的计算结果“广播”到组内的每一行,保证新列和原DataFrame长度一致lambda x: (x == 'Email').sum():在每个客户组里,判断ActivityType是否为Email,然后求和得到该客户的总Email次数
方法二:用交叉表+合并
如果你更习惯先统计再合并,也可以用pd.crosstab生成客户-活动类型的计数表,再合并回原数据:
import pandas as pd df = pd.DataFrame({ 'CustomerID': ['01134A', '01134B', '01134A', '01134B'], 'ActivityType': ['Email', 'Email', 'Call', 'Email'] }) # 生成每个客户的各活动类型计数表 counts = pd.crosstab(df['CustomerID'], df['ActivityType']).fillna(0).astype(int) # 合并回原DataFrame df = df.merge(counts, left_on='CustomerID', right_index=True, how='left') # 重命名列名符合你的需求 df = df.rename(columns={'Email': 'TotalEmail', 'Call': 'TotalCall'}) print(df)
这个方法也能得到完全一样的结果,适合需要先查看整体计数情况的场景。
内容的提问来源于stack exchange,提问作者Esther
相关产品推荐
相关产品推荐

