簡體   English   中英

如何使用NumPy / SciPy計算運動/運行/滾動任意函數(例如峰度和偏度)

[英]How to calculate moving / running / rolling arbitrary function (e.g. kurtosis & skewness) using NumPy / SciPy

我正在處理時間序列數據。 為了從數據中獲取特征,我必須計算移動平均值,中位數, scipy.statscipy.stat ,峰度,偏度等。我熟悉scipy.stat ,它提供了一種簡單的方法來計算這些量以進行直接計算。 但是對於運動/跑步部分,我已經瀏覽了整個互聯網,但一無所獲。

令人驚訝的是,移動平均數,中位數和numpy非常容易用numpy計算。 不幸的是,沒有用於計算峰度和偏度的內置函數。 如果有人可以提供幫助,如何用scipy計算運動的峰度和偏度? 非常感謝

熊貓提供了一個DataFrame.rolling()方法,可以將其與Rolling.apply()方法(即df.rolling().apply() )結合使用,以將任意函數應用於指定的滾動窗口。


如果您正在尋找基於NumPy的解決方案,則可以使用FlyingCircus (免責聲明:我是它的主要作者)。

在那里,您可以找到以下內容:

  1. flyingcircus.extra.running_apply() :可以將任何函數應用於一維數組並支持權重,但速度較慢;
  2. flyingcircus.extra.moving_apply() :可以將支持axis: int參數的任何函數應用於一維數組並支持權重,並且速度很快(但需要大量內存);
  3. flyingcircus.extra.rolling_apply_nd() :可以將支持axis: int|Sequence[int]參數的任何函數應用於任何ND數組,並且速度快(且節省內存),但不支持權重。

根據您的要求,我建議使用rolling_apply_nd() ,例如:

import numpy as np
import scipy as sp
import flyingcircus as fc

import scipy.stats


NUM = 30
arr = np.arange(NUM)

window = 4
new_arr = fc.extra.rolling_apply_nd(arr, window, func=sp.stats.kurtosis)
print(new_arr)
# [-1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36
#  -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36 -1.36
#  -1.36 -1.36 -1.36]

當然,可以隨時檢查源代碼 ,它是開源(GPL)。


編輯

只是為了了解我們正在談論的那種速度,以下是FlyingCircus中實現的解決方案的基准:

基准 Benchmark_zoom

一般方法flyingcircus.extra.running_apply()flyingcircus.extra.rolling_apply_nd()flyingcircus.extra.moving_apply()慢幾個數量級,第一個大約是。 比第二個快一個數量級。 這顯示了通用性或權重支持的速度價格。

上面的圖是使用此處的腳本和以下代碼獲得的:

import scipy as sp
import flyingcircus as fc
import scipy.stats


WINDOW = 4
FUNC = sp.stats.kurtosis


def my_rolling_apply_nd(arr, window=WINDOW, func=FUNC):
    return fc.extra.rolling_apply_nd(arr, window, func=FUNC)


def my_moving_apply(arr, window=WINDOW, func=FUNC):
    return fc.extra.moving_apply(arr, window, func)


def my_running_apply(arr, window=WINDOW, func=FUNC):
    return fc.extra.running_apply(arr, window, func)


def equal_output(a, b):
    return np.all(np.isclose(a, b))


input_sizes = (5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000)
funcs = my_rolling_apply_nd, my_moving_apply, my_running_apply

runtimes, input_sizes, labels, results = benchmark(
    funcs, gen_input=np.random.random, equal_output=equal_output,
    input_sizes=input_sizes)

plot_benchmarks(runtimes, input_sizes, labels, units='s')
plot_benchmarks(runtimes, input_sizes, labels, units='ms', zoom_fastest=8)

在玩耍之后,我想出了一個純粹基於numpyscipy的解決方案。 當然,它使用的是scipy.stats kurtosisskew

import numpy as np
from scipy.stats import kurtosis, skew

# Window size
N = 4

# Some random data
m = np.array([2, 3, 10, 11, 0, 4, 8, 2, 5, 9])

# Running Kurtosis
def runningKurt(x, N):
    # Initilize placeholder array
    y = np.zeros((len(x) - (N - 1),))
    for i in range(len(x) - (N - 1)):

         y[i] = kurtosis(x[i:(i + N)])

    return y

# Running Kurtosis

def runningSkew(x, N):
    # Initilize placeholder array
    y = np.zeros((len(x) - (N - 1),))
    for i in range(len(x) - (N - 1)):

         y[i] = skew(x[i:(i + N)])

    return y

kurt = runningKurt(m, N)
print("kurtosis : ", kurt)
# kurtosis :  [-1.93940828 -1.77879935 -1.61464214 -1.40236694 -1.15428571 -1.07626667 -1.42666667]


skw = runningSkew(m, N)
print("skew : ", skw)
# skew :  [ 0.         -0.1354179  -0.26356495 -0.13814702  0.43465076  0.32331615 -0.36514837]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM