是否有开源函数来计算移动的z-score,如https://turi.com/products/create/docs/generated/graphlab.toolkits.anomaly_detection.moving_zscore.create.html。我可以访问pandas rolling_std来计算std,但是想看看它是否可以扩展到计算滚动z分数。
答案 0 :(得分:10)
rolling.apply
明显慢于使用内置滚动函数(例如mean和std)。因此,从滚动平均值和滚动标准计算滚动z得分:
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
根据this page给出的定义,滚动z得分取决于当前点之前的滚动均值和标准。上面使用shift(1)
来实现此效果。
下面,即使是小型系列(长度为100),zscore
的速度也比使用rolling.apply
快5倍。由于rolling.apply(zscore_func)
在基本上是Python循环中为每个滚动窗口调用zscore_func
一次,因此使用Cythonized r.mean()
和r.std()
函数的优势变得更加明显。循环增加。
因此,随着系列的长度增加,zscore
的速度优势增加。
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()
答案 1 :(得分:1)
我们假设您有一个名为data的数据框,如下所示:
然后运行以下代码,
data_zscore = data.apply(lambda x:(x-x.expanding()。mean())/ x.expanding()。std())
enter image description here 请注意,第一行将始终具有NaN值,因为它没有标准偏差。
答案 2 :(得分:0)
您应该使用熊猫的本机功能:
# Compute rolling zscore for column ="COL" and window=window
col_mean = df["COL"].rolling(window=window).mean()
col_std = df["COL"].rolling(window=window).std()
df["COL_ZSCORE"] = (df["COL"] - col_mean)/col_std
答案 3 :(得分:0)
def zscore(arr, window):
x = arr.rolling(window = 1).mean()
u = arr.rolling(window = window).mean()
o = arr.rolling(window = window).std()
return (x-u)/o
df['zscore'] = zscore(df['value'],window)