我正在尝试使用pandas.DataFrame.rolling
实现以下目标:
位于索引 i
,我要滚动sum
, mean
, median
,...最后size_win
使用 parzen
的值 window 。仅考虑过去的值(即索引 <i
)并且不考虑 future 的任何值(这是“我们在时间i
?”场景)。第二个约束是:我想要一个单面的parzen
窗口,即索引 i
处的值应该获得最大权重,i-1
更小的重量,i-2
更小的重量,...,i-size_win
最小重量。
使用标准
df.rolling(window=size_win, win_type='parzen').sum()
对我不起作用,因为它会给出索引 i
最小重量和 i-(size_win/2)
最大重量。供应center
参数将给出索引 i
最大重量还能用 future >i
计算值。
我使用 pandas.DataFrame.rolling(...).apply
找到了解决方案但这(当然)非常慢。
请参阅以下示例:
import time
import pandas as pd
import scipy as sp
import numpy as np
df = pd.DataFrame(np.random.randint(0,100,size=(100000, 4)), columns=list('ABCD'))
size_win = 1000
def window_single_sided_parzen(window_size):
return sp.signal.parzen((window_size-1)*2+1)[0:window_size]
def custom_rolling_sum(x, window):
return (x * window).sum()
t_start = time.time()
df_rolled_fast = df.rolling(window=size_win, win_type='parzen').sum()
print(f'Run time of builtin: {time.time() - t_start:.2f} s')
t_start = time.time()
df_rolled = df.rolling(window=size_win).apply(lambda x: custom_rolling_sum(x, window_single_sided_parzen(size_win)))
print(f'Run time of apply: {time.time() - t_start:.2f} s')
在我的例子中,内置滚动需要 1.3 秒(没有产生我想要的结果),而我自己的解决方案需要 54 秒。
有什么想法可以更有效地解决这个问题吗?
最佳答案
发现我自己的推理错误:
df_rolled = df.rolling(window=size_win).apply(lambda x: custom_rolling_sum(x, window_single_sided_parzen(size_win)))
我天真地认为,它只会调用一次昂贵的函数window_single_side_parzen(size_win)
。事实上,每一行都会调用它。切换至
win = window_single_sided_parzen(size_win)
df_rolled = df.rolling(window=size_win).apply(lambda x: custom_rolling_sum(x, win))
速度要快得多。不如内置功能那么快,但足够快。
关于python - Pandas 在单面 window 上滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46392768/