Python循环中DataFrame滚动均值的高效计算方案问询
高效实现依赖前序行的滚动均值计算
场景1:仅计算滚动均值(无其他列依赖)
如果你的需求只是生成示例中的滚动均值列,完全不需要循环,直接用pandas的向量化滚动操作即可,这是性能最优的方式:
import pandas as pd # 构造示例数据 df = pd.DataFrame({ 'Minute': [1, 2, 3, 4, 5, 6], 'Value': [3, 5, 8, 4, 6, 7] }) n_periods = 3 # 计算窗口为3的滚动均值,min_periods=1保证窗口不足时也能计算(后续覆盖前两行) df['Rolling Mean'] = df['Value'].rolling(n_periods, min_periods=1).mean(skipna=False) # 将前n_periods-1行的均值设为0,匹配示例要求 df.loc[:n_periods-2, 'Rolling Mean'] = 0
运行后结果与示例完全一致,向量化操作的速度远快于循环,即使处理数十万行数据也能瞬间完成。
场景2:多列彼此依赖,必须逐行计算
如果业务逻辑中,滚动均值或其他指标依赖于之前行的计算结果(比如当前行的指标会影响下一行的滚动均值),此时需要逐行循环,但可以通过递推公式优化计算,避免重复遍历窗口内元素:
滚动均值的递推逻辑:维护一个窗口内的数值总和,每次仅需加减当前值和窗口最左侧的旧值,无需重新计算整个窗口的均值:
import pandas as pd df = pd.DataFrame({ 'Minute': [1, 2, 3, 4, 5, 6], 'Value': [3, 5, 8, 4, 6, 7] }) n_periods = 3 df['Rolling Mean'] = 0.0 window_sum = 0 # 维护窗口内的数值总和 for i in range(len(df)): current_val = df.at[i, 'Value'] window_sum += current_val # 当窗口长度超过n_periods时,减去窗口最左侧的旧值 if i >= n_periods: window_sum -= df.at[i - n_periods, 'Value'] # 仅当窗口长度达标时计算均值,否则保持0 if i >= n_periods - 1: df.at[i, 'Rolling Mean'] = window_sum / n_periods
这种循环每次仅做O(1)计算,相比你之前每次循环调用rolling(O(n)复杂度),性能提升非常明显,处理数千行数据毫无压力。
为什么你原来的逐行代码无法运行
你尝试的df.at[i, 'Value'].rolling(...)会报错,因为df.at[i, 'Value']返回的是单个标量值,而rolling方法只能作用于Series或DataFrame,不能作用于标量。
内容的提问来源于stack exchange,提问作者PythonNoob
相关产品推荐
相关产品推荐

