如何对pandas Series直接调用apply应用scipy.savgol_filter?
问题根源
你对报错原因的判断完全正确:Series.apply() 方法的设计逻辑是逐元素遍历序列,每次仅传入单个数值到自定义函数中,自然无法满足 savgol_filter 要求的窗口长度≥7的条件。同时 Series.apply 没有类似DataFrame的axis参数可以调整为传入整列数据。
可行解决方案
方案1:使用 rolling.apply 实现(符合你要用apply方法的需求)
如果需要通过apply类方法实现,搭配pandas的滑动窗口接口即可,设置center=True保证滤波后序列和原序列索引对齐,raw=True可以大幅提升运算性能:
import pandas as pd import numpy as np from scipy.signal import savgol_filter s = pd.Series(np.random.rand(20), index=np.arange(20)) def smooth(x): # 窗口长度7,取中间位置的计算结果对应原序列当前索引的数值 return savgol_filter(x, 7, 3, mode='nearest')[3] s_smoothed = s.rolling(window=7, center=True, min_periods=7).apply(smooth, raw=True)
运算结果为pandas.Series类型,完全保留原序列的索引。
方案2:直接包装滤波结果(更简洁高效)
你提到不想直接调用smooth(s)的核心顾虑是返回numpy数组,只需要在外部套一层Series构造方法即可解决,性能远高于逐窗口apply:
def smooth(x): return savgol_filter(x, 7, 3) s_smoothed = pd.Series(smooth(s), index=s.index)
该写法代码量更少,运算速度更快,同样可以保留Series的所有属性。
内容的提问来源于stack exchange,提问作者Stardust
相关产品推荐
相关产品推荐

