np.cumsum() 默认将数组展平为一维后累加,非按行或列;需显式指定 axis=0(列向)或 axis=1(行向);金融中普通收益率不可直接 cumsum,应转增长因子后用 cumprod;遇 NaN/inf 会污染后续结果;默认 dtype 继承输入,建议金融计算统一用 float64。

np.cumsum() 默认按行还是按列累加
默认是把整个数组展平成一维再累加,不是按行也不是按列——这点很多人第一次用就踩坑。比如二维数组 arr = np.array([[1, 2], [3, 4]]),np.cumsum(arr) 返回 [1, 3, 6, 10],而不是你可能以为的按 axis=0 或 axis=1 的结果。
要控制方向,必须显式传 axis 参数:
-
axis=0:对每一列从上到下累加(纵向) -
axis=1:对每一行从左到右累加(横向) -
axis=None(默认):等价于先arr.flatten()再累加
金融场景下算累计收益率为什么不能直接 cumsum
因为收益率是乘积关系,不是加法关系。日收益率 [0.01, -0.02, 0.015] 对应的累计收益不是 np.cumsum([0.01, -0.02, 0.015]),而是 (1+r₁)×(1+r₂)×(1+r₃) − 1。
正确做法是先转成增长因子,再用 np.cumprod(),最后减 1:
rets = np.array([0.01, -0.02, 0.015]) growth_factors = 1 + rets cum_rets = np.cumprod(growth_factors) - 1 # [0.01, -0.0102, 0.004647]
如果硬要用 np.cumsum(),只适用于对数收益率(log returns),因为 log(1+r) ≈ r 且满足可加性,但实盘中原始数据几乎都是普通收益率。
np.cumsum() 处理 NaN 和 inf 的行为
np.cumsum() 遇到 np.nan 就会“污染”后续所有结果:第一个 nan 出现后,它及之后所有值都变成 nan;遇到 np.inf 则后续全为 inf 或 -inf,不会报错但结果失效。
常见错误场景:用它处理含缺失值的股价序列,结果整列变 nan。
稳妥做法是先填充或剔除:
- 前向填充:
np.cumsum(np.nan_to_num(arr, nan=0))(慎用,0 可能不适用) - 跳过 NaN:
np.cumsum(np.where(np.isnan(arr), 0, arr)),但逻辑上不严谨 - 更合理的是先用
pandas.Series.fillna(method='ffill')或明确业务规则插值,再喂给np.cumsum()
dtype 影响精度和内存,尤其在长序列中
np.cumsum() 输出 dtype 默认继承输入数组 dtype。如果输入是 float32,累积过程可能因舍入误差快速放大;如果输入是 int64 但累加结果超范围,会静默溢出(比如从正变负),不报错也不警告。
建议根据场景主动指定 dtype:
- 金融计算一律用
dtype=np.float64 - 整数索引类累加(如生成序号)可用
dtype=int,但要确认不会溢出 - 用
out参数复用数组可省内存:np.cumsum(arr, out=result_arr)
长序列(千万级)做 np.cumsum() 时,float64 虽慢一点但安全;float32 看似快,但第 10⁶ 步后误差可能已超 1e-3,对收益率这类敏感值不可接受。










