cumsum 在 dataframe 中默认按列纵向累加(axis=0),而非横向;对单列用 df['col'].cumsum(),多列用 df[['a','b']].cumsum();groupby 后需 df.groupby('cat')['col'].cumsum() 或 df.groupby('cat')[['a','b']].cumsum()。

cumsum 在 DataFrame 里默认按行还是按列算?
默认按行(即对每一列单独累计),不是按行方向横向累加。这是新手最常误解的点——看到 cumsum 就以为“从左到右加”,其实它默认 axis=0,也就是纵向沿索引方向累加。
- 想按行横向累计?必须显式写
cumsum(axis=1) - 对某列单独用:直接
df['col'].cumsum(),返回Series,不改变原df - 对多列批量操作:
df[['a', 'b']].cumsum(),结果仍是DataFrame,每列独立计算 - 遇到
NaN会中断:首个NaN后面全变成NaN,不是跳过,这点和sum不同
groupby 后怎么用 cumsum 做分组内累计?
不能直接 df.groupby('cat').cumsum() —— 这会报错 AttributeError: 'DataFrameGroupBy' object has no attribute 'cumsum'。正确做法是把 cumsum 放在 apply 或直接作用于被分组的列上。
- 对单列分组累计:
df.groupby('cat')['value'].cumsum(),返回和原df等长的Series - 对多列统一按组累计:
df.groupby('cat')[['a', 'b']].apply(lambda x: x.cumsum()),但注意这会重置索引,更稳写法是df.groupby('cat')[['a', 'b']].cumsum()(Pandas ≥ 1.3 支持) - 想按时间排序后再累计?先
sort_values('date'),再groupby,顺序错会导致结果完全不对
cumsum 结果变 float 是因为原始数据有 NaN?
是的。只要参与计算的列里有一个 NaN,cumsum 输出类型就会自动升为 float64,哪怕原始是 int64。这不是 bug,是 Pandas 的类型安全策略——NaN 在整数中无法表示,只能转浮点。
- 不想转 float?先用
fillna(0),但注意:填 0 会改变业务逻辑(比如“未发生”和“发生但为 0”不同) - 保留 int 类型且允许缺失?用可空整型:
df['col'] = df['col'].astype('Int64')(注意大写I),再cumsum仍返回Int64,NaN保持为<na></na> - 性能提示:可空整型比普通
int64慢约 2–3 倍,大数据量时得权衡
用 cumsum 做“截止到当前的累计占比”要注意什么?
常见写法 df['pct'] = df['val'].cumsum() / df['val'].sum() 看似合理,但容易在分组或动态窗口场景下出错——分母如果没对齐分组,结果就全乱了。
- 分组内占比:必须确保分子分母都基于同一组,比如
df.groupby('cat')['val'].transform('cumsum') / df.groupby('cat')['val'].transform('sum') - 滚动窗口累计?
cumsum本身不支持窗口,得换rolling(n).sum(),别硬套 - 精度陷阱:浮点除法可能让最后一条记录的累计占比 ≠ 1.0,做判断时别用
== 1.0,改用np.isclose(..., 1.0)
cumsum 这一行代码,而是它前面的数据清洗顺序、分组键是否稳定、以及 NaN 出现在哪一环——这些地方一错,结果看着像对,其实已经偏了。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











