计算pandas数据帧中的滚动z得分

use*_*827 9 python pandas

是否有开源函数来计算移动的z-score,如https://turi.com/products/create/docs/generated/graphlab.toolkits.anomaly_detection.movi​​ng_zscore.create.html.我可以访问pandas rolling_std来计算std,但是想看看它是否可以扩展到计算滚动z分数.

unu*_*tbu 12

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
Run Code Online (Sandbox Code Playgroud)

根据本页给出的定义,滚动z得分取决于当前点之前的滚动均值和标准.在shift(1)上面用来达到这种效果.


下面,即使是小型系列(长度为100),zscore也比使用速度快5倍rolling.apply.由于rolling.apply(zscore_func)呼叫zscore_func在基本上一个Python循环各轧制窗口一次,使用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
Run Code Online (Sandbox Code Playgroud)

这是用于基准测试的设置:

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()
Run Code Online (Sandbox Code Playgroud)

  • 我们是否需要在这里使用 `shift()` 函数,因为 `rolling()` 函数会在给定的时间内很好地处理它。不是吗?? (3认同)
  • 我认为你是对的@id101112 - 不需要 `shift()` ,因为你已经在 `window` 时间“看到”了数据,所以将 z_score 计算为该值是合理的。 (2认同)

del*_*nce 8

您应该使用熊猫的本机功能:

 # 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
Run Code Online (Sandbox Code Playgroud)