In [58]: %timeit zscore(x, N)
1000 loops, best of 3: 903 µs per loop
In [59]: %timeit zscore_using_apply(x, N)
100 loops, best of 3: 4.84 ms per loop
这是用于基准测试的设置:
import numpy as np
import pandas as pd
np.random.seed(2017)
def zscore(x, window):
r = x.rolling(window=window)
m = r.mean().shift(1)
s = r.std(ddof=0).shift(1)
z = (x-m)/s
return z
def zscore_using_apply(x, window):
def zscore_func(x):
return (x[-1] - x[:-1].mean())/x[:-1].std(ddof=0)
return x.rolling(window=window+1).apply(zscore_func)
N = 5
x = pd.Series((np.random.random(100) - 0.5).cumsum())
result = zscore(x, N)
alt = zscore_using_apply(x, N)
assert not ((result - alt).abs() > 1e-8).any()
带有自定义函数的
rolling.apply
比使用内置滚动函数(如mean和std)慢得多。因此,根据滚动平均值和滚动标准计算滚动z分数:根据this page上给出的定义,滚动z-得分取决于当前点之前的滚动平均值和std。为了达到这个效果,上面使用了
shift(1)
。下面,即使是一个小序列(长度为100),
zscore
比使用rolling.apply
快5倍以上。由于rolling.apply(zscore_func)
对Python循环中的每个滚动窗口调用zscore_func
一次,因此随着循环大小的增加,使用Cythonizedr.mean()
和r.std()
函数的优势变得更加明显。 因此,随着级数长度的增加,zscore
的速度优势增大。这是用于基准测试的设置:
假设您有一个名为data的数据帧,如下所示:
enter image description here
然后运行以下代码
data_zscore=data.apply(lambda x:(x-x.expanding().mean())/x.expanding().std())
enter image description here 请注意,第一行将始终具有NaN值,因为它没有标准偏差。
您应该使用熊猫的本地功能:
相关问题 更多 >
编程相关推荐