首页 > 解决方案 > pandas 中的动态滚动功能

问题描述

我正在尝试在 Pandas中实现动态移动平均线std和其他动态移动函数。max“正常”和动态移动平均线之间的区别在于边缘的行为。这主要改善了两件事:

因此,要获得动态移动平均线,有多种方法,如反射、第一个/最后一个值的重复…… 对我来说,反射方法就足够了。这和其他行为在过滤器中实现scripy.ndimage.filters,例如uniform_filter1d. 我已经查看了 Pandas 文档,但是rolling我找不到任何改变边缘行为的参数......我自己添加这个似乎是可行的,但我问这个问题,看看我是否已经在 Pandas 中有一个实现错过了。

所以我的问题可以简化为:有没有办法rolling像我描述的那样动态使用 Pandas?

“正常”移动平均线

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import filters


def moving_avg(series: pd.Series, window: int) -> pd.Series:
    return series.rolling(window=window).mean()


t = np.linspace(0, 100, 1000)
y = np.sin(2 * np.pi * 0.03 * t)

filtered_y = filters.uniform_filter1d(y, 200)

pd_y = pd.Series(y, name="Pandas Moving Average")
pd_y = moving_avg(pd_y, 200) # Using a large window on purpose to show the shift!

plt.plot(y, label="Raw Data")
plt.plot(filtered_y, label="uniform_filter1d")
pd_y.plot()
plt.legend()
plt.show()

结果

滚动行为的差异

那么有什么办法可以解决这个问题吗?

标签: pythonpandasnumpyscipysignal-processing

解决方案


我不认为有你想要实现的东西。一种简单的方法是使用concat添加边缘值来创建反射效果。在一个函数中,它可能类似于

def rolling_reflect_center(s, window):
    nb_ref = window // 2
    rolling_ = pd.concat(
        [pd.Series(s.iloc[:nb_ref].values)[::-1],#reflect on the left
         s, 
         pd.Series(s.iloc[-nb_ref+1:].values[::-1]) #reflect on the right
        ]).rolling(window ,center=True)
    return rolling_

然后你做

filtered_y = filters.uniform_filter1d(y, 200)

pd_y = pd.Series(y, name="Pandas Moving Average")
pd_y = rolling_reflect_center( pd_y, window=200).mean()

print(np.allclose(pd_y.dropna().to_numpy(),filtered_y))
#True

情节也很好,因为它会nan自动放弃


推荐阅读