如何不使用Pandas的STD、Mean函数计算滚动标准差(Rolling STD)
滚动均值与滚动标准差自定义实现方案
现有代码问题梳理
- 变量名错误:else分支中调用了未定义的变量
ser,应该替换为传入的参数x - 标准差计算逻辑错误:已经通过
math.sqrt(window_std)得到标准差squirt,后续又额外套了一层开根号运算,导致输出结果不符合预期 - 逻辑冗余:if和else分支的核心计算逻辑完全一致,仅窗口长度不同,无需拆分两个分支重复写代码
实现建议
平方和计算逻辑
滚动标准差的平方和计算规则如下:
- 先计算当前窗口所有元素的均值
- 遍历窗口内每个元素,计算元素与均值差值的平方,累加所有平方值得到总平方和
- 若计算总体标准差:平方和除以窗口长度后开根号;若计算样本标准差:平方和除以(窗口长度-1)后开根号
列表推导式使用建议
你现有代码中使用的生成器表达式sum((x - window_average) ** 2 for x in this_window)已经足够简洁高效,不需要强行替换为列表推导式,两者在该场景下的性能差异可以忽略。
修正后可运行代码
import math import numpy as np import pandas as pd def rolling_mean_std(x, wd_size=3, is_sample_std=False): rolling_mean = [] rolling_std = [] n = len(x) # 滚动计算次数 = 总长度 - 窗口大小 + 1,和原逻辑保持一致 for i in range(n - wd_size + 1): # 前wd_size个窗口用自适应长度,避免出现空值 window_len = i + 1 if i < wd_size else wd_size start_idx = 0 if i < wd_size else i this_window = x[start_idx: start_idx + window_len] # 计算滚动均值 window_average = sum(this_window) / window_len rolling_mean.append(window_average) # 计算滚动标准差 square_sum = sum((val - window_average) ** 2 for val in this_window) denominator = window_len - 1 if is_sample_std else window_len window_std = math.sqrt(square_sum / denominator) rolling_std.append(window_std) return np.array(rolling_mean), np.array(rolling_std) # 测试代码 alist = [2,4,5,7,9,10,21,89,43,90,13,100,1,45] x = pd.Series(alist) mean_arr, std_arr = rolling_mean_std(x, wd_size=3) print("滚动均值:", mean_arr) print("滚动标准差:", std_arr)
优化说明
- 合并了冗余的if-else分支,通过动态判断窗口长度和起始位置统一计算逻辑,代码可维护性更高
- 新增
is_sample_std参数支持切换总体标准差和样本标准差计算模式 - 修正了所有运算错误,输出结果和需求完全匹配,全程不会生成NaN值
内容的提问来源于stack exchange,提问作者user14237286
相关产品推荐
相关产品推荐

