
使用 DataFrame.groupby().sum() 时,Pandas 会默认对所有数值列求和,但对字符串列执行连接(concatenation),导致如 "A" + "B" + "C" → "ABC" 的意外结果;正确做法是显式排除非数值列或指定聚合函数。
使用 `dataframe.groupby().sum()` 时,pandas 会默认对所有数值列求和,但对字符串列执行连接(concatenation),导致如 "a" + "b" + "c" → "abc" 的意外结果;正确做法是显式排除非数值列或指定聚合函数。
在 Pandas 中,groupby(...).sum() 是一个便捷但隐式类型敏感的操作:它会对所有可求和的列(包括字符串)调用其 + 运算符。对于字符串,+ 表示拼接,因此分组后 col_3(如类别型字符串 'A', 'B', 'C')会被串联成类似 'AACBB' 的无意义组合——这既非统计需求,也易引发逻辑错误。
✅ 正确解决方案
方法一:提前剔除非数值列(推荐)
最直接、安全的方式是在 groupby 前用 .drop(columns=...) 移除字符串列:
# 仅对数值列 col_4 进行分组求和 result = df.drop(columns='col_3').groupby(['col_1', 'col_2']).sum()
该方法清晰表达意图,避免副作用,且性能高效。
方法二:使用 agg() 显式指定每列聚合方式
当需保留字符串列并做有意义聚合(如取众数、首值、唯一值列表)时,应使用 agg 并按列定制函数:
result = df.groupby(['col_1', 'col_2']).agg({
'col_3': lambda x: x.mode().iloc[0] if not x.mode().empty else None, # 众数(最频繁值)
'col_4': 'sum'
})
也可简写为:
result = df.groupby(['col_1', 'col_2']).agg({
'col_3': 'first', # 或 'last', 'nunique', lambda x: ', '.join(x.unique())
'col_4': 'sum'
})
方法三:利用 select_dtypes() 自动筛选数值列
适用于列较多、类型混杂的场景,避免手动列举:
numeric_cols = df.select_dtypes(include=np.number).columns result = df.groupby(['col_1', 'col_2'])[numeric_cols].sum()
⚠️ 注意事项
- ❌ 避免直接对含字符串列的 DataFrame 调用 .sum() 做分组聚合,除非明确需要字符串拼接(极少见);
- ✅ 检查 df.dtypes 确认列类型,尤其注意 object 类型是否真为字符串(而非未转为 category 的分类变量);
- ? 若 col_3 实为类别变量(如性别、地区),建议先转为 pd.Categorical,再用 agg({'col_3': 'mode'}) 或 agg({'col_3': pd.Series.mode}) 获取统计意义更强的结果;
- ? sum() 对布尔列等价于计数(True=1),但对字符串永远是拼接——这是设计行为,非 bug,务必主动规避。
总之,Pandas 的聚合操作遵循“列导向”而非“语义导向”,开发者需主动控制参与聚合的列及其函数,而非依赖默认行为。显式优于隐式,安全始于类型意识。











