Pandas:按ID分组后按条件统计New出现次数返回NaN的问题排查
问题分析与解决方案
这个问题的核心是索引不匹配!当你用groupby.apply()的时候,返回结果的索引是分组的唯一键(也就是a、b、c),而原DataFrame的索引是原始行索引(0、1、2、3、4),直接赋值时pandas找不到对应关系,所以全部变成了NaN。
下面给你几种简单有效的解决办法:
方法1:用transform代替apply(最推荐)
transform会自动把分组统计的结果广播到原DataFrame的每一行,保持索引完全匹配,完美解决这个问题:
df['NewAmount'] = df.groupby('ID')['Type'].transform(lambda x: (x == 'New').sum())
这里用(x == 'New').sum()代替x[x == 'New'].count(),效果完全一致,但写法更简洁——布尔值会被当作1和0处理,求和就是统计New的出现次数。
方法2:先统计再映射
如果你更习惯用apply,可以先把分组统计结果存成一个Series,再用map把对应值映射到原DataFrame:
# 先计算每个ID的New出现次数 new_count_series = df.groupby('ID')['Type'].apply(lambda x: x[x == 'New'].count()) # 把结果映射到原DataFrame的每一行 df['NewAmount'] = df['ID'].map(new_count_series)
这样每个行的ID会对应到new_count_series里的统计值,比如所有ID=b的行都会拿到2,ID=c的行拿到0。
方法3:用value_counts+unstack
另一种更直观的统计方式,先算出每个ID下不同Type的数量,再提取New列的值映射回去:
# 统计每个ID下各Type的数量,缺失项填充0 type_counts = df.groupby('ID')['Type'].value_counts().unstack(fill_value=0) # 把New列的结果映射到原DataFrame df['NewAmount'] = df['ID'].map(type_counts['New'])
运行以上任意一种方法后,你都会得到预期的结果:
| ID | Type | NewAmount |
|---|---|---|
| a | New | 1 |
| b | Old | 2 |
| b | Old | 2 |
| b | New | 2 |
| c | Old | 0 |
内容的提问来源于stack exchange,提问作者mokiliii Lo
相关产品推荐
相关产品推荐

