You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算Pandas DataFrame中每行对应过去n行的标准差?

优化Pandas中计算滚动标准差的效率问题

你现在用iterrows()循环逐行计算过去n行的标准差,这种方法在数据量稍大的时候会变得非常慢——毕竟iterrows()是逐行迭代,每次还要做切片计算,时间复杂度是O(m*n)(m是DataFrame的行数),而且直接用df['std'][i]赋值还可能触发SettingWithCopyWarning,甚至导致意外的修改行为。

最优解决方案:用Pandas内置的rolling()方法

Pandas专门提供了rolling()API来处理这类滚动窗口统计计算,完全不需要手动循环,底层是向量化的C实现,效率比循环高几个数量级,代码也更简洁。

场景1:计算包含当前行在内的过去n行的标准差

比如你提到的「行索引为100、n=25时,计算索引76到100区间(共25行)的标准差」,直接用下面的代码:

n = 25
df['std'] = df['Close'].rolling(window=n).std()
  • window=n:指定滚动窗口的大小为n行
  • 默认情况下,前n-1行因为数据不足n个,会返回NaN;如果希望前n-1行用已有数据计算标准差(比如第5行用前5行的数据),可以加上min_periods=1参数:
    df['std'] = df['Close'].rolling(window=n, min_periods=1).std()
    

场景2:计算当前行之前的n行(不包含当前行)的标准差

如果你需要的是「行索引为100时,计算索引75到99区间(共25行)的标准差」,只需要在rolling()后加shift(1),把结果下移一行即可:

df['std'] = df['Close'].rolling(window=n).std().shift(1)

为什么你的原代码效率低?

  1. iterrows()的性能问题:逐行迭代本质上是Python层面的循环,远不如Pandas底层的向量化操作高效,当DataFrame有上万行甚至更多时,差距会非常明显。
  2. 链式索引的风险:df['std'][i]属于链式索引,Pandas无法确定你是在修改原DataFrame还是一个副本,容易触发SettingWithCopyWarning,正确的赋值方式应该是df.loc[i, 'std'],但即使修正了这一点,循环的效率依然很低。
  3. 切片逻辑易出错:你原代码中的切片写法,在索引不是连续整数的时候会出现逻辑错误,而rolling()会自动处理各种索引类型,无需手动计算切片范围。

完整测试示例

import pandas as pd
import numpy as np

# 生成1000行测试数据
np.random.seed(42)
df = pd.DataFrame({'Close': np.random.randn(1000)})
n = 25

# 计算包含当前行的滚动标准差
df['std_rolling'] = df['Close'].rolling(window=n).std()

# 计算当前行之前n行的标准差(不包含当前行)
df['std_rolling_past'] = df['Close'].rolling(window=n).std().shift(1)

内容的提问来源于stack exchange,提问作者Don Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:08:00