簡體   English   中英

滾動 window 用於 Numpy 中的一維 arrays?

[英]Rolling window for 1D arrays in Numpy?

有沒有辦法有效地為 Numpy 中的一維 arrays 實現滾動 window?

例如,我有這個純 Python 代碼片段來計算一維列表的滾動標准差,其中observations是一維值列表, n是標准差的 window 長度:

stdev = []
for i, data in enumerate(observations[n-1:]):
    strip = observations[i:i+n]
    mean = sum(strip) / n
    stdev.append(sqrt(250*sum([(s-mean)**2 for s in strip])/(n-1)))

有沒有辦法在 Numpy 中完全做到這一點,即沒有任何 Python 循環? numpy.std的標准偏差微不足道,但滾動的 window 部分完全讓我難過。

我發現 這篇關於 Numpy 中滾動 window 的博客文章,但它似乎不適用於一維 arrays。

只需使用博客代碼,但將您的函數應用於結果。

IE

numpy.std(rolling_window(observations, n), 1)

你在哪里(來自博客):

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

我嘗試在形狀為[samples, features]的二維數組上使用上面列出的so12311答案[samples, features]以獲得形狀為[samples, timesteps, features]的輸出數組,用於卷積或 lstm 神經網絡,但它不是' t 工作得很好。 在深入研究 strides 的工作原理后,我意識到它是沿着最后一個軸移動窗口,所以我做了一些調整,以便窗口沿着第一個軸移動:

def rolling_window(a, window_size):
    shape = (a.shape[0] - window_size + 1, window_size) + a.shape[1:]
    strides = (a.strides[0],) + a.strides
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

注意:如果您僅使用一維輸入數組,則輸出沒有區別。 在我的搜索中,這是第一個接近我想要做的結果,所以我添加它是為了幫助任何其他人尋找類似的答案。

只有一行代碼...

import pandas as pd

pd.Series(observations).rolling(n).std()

Numpy 1.20開始,您可以直接使用sliding_window_view獲得滾動窗口:

from numpy.lib.stride_tricks import sliding_window_view

sliding_window_view(np.array([1, 2, 3, 4, 5, 6]), window_shape = 3)
# array([[1, 2, 3],
#        [2, 3, 4],
#        [3, 4, 5],
#        [4, 5, 6]])
def moving_avg(x,n):
    mv =  np.convolve(x,np.ones(n)/n,mode='valid')
    return np.concatenate(([np.NaN for k in range(n-1)],mv))

基於后面的答案,我在這里添加了用於滾動一維 numpy 數組選擇窗口大小窗口步長頻率的代碼

a = np.arange(50)

def rolling_window(array, window_size,freq):
    shape = (array.shape[0] - window_size + 1, window_size)
    strides = (array.strides[0],) + array.strides
    rolled = np.lib.stride_tricks.as_strided(array, shape=shape, strides=strides)
    return rolled[np.arange(0,shape[0],freq)]

rolling_window(a,10,5)

輸出:

array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [ 5,  6,  7,  8,  9, 10, 11, 12, 13, 14],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [25, 26, 27, 28, 29, 30, 31, 32, 33, 34],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [35, 36, 37, 38, 39, 40, 41, 42, 43, 44],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49]])

我需要一個滾動的 window 來應用於 n 維數組的任何中間軸,所以我從已經接受的答案和@Miguel Gonzalez 擴展了代碼。 將滾動 window 應用於沿任意軸的 nd 數組的相應代碼:

def rolling_window(array, window, freq, axis=0):
    shape = array.shape[:axis] + (array.shape[axis] - window_size + 1, window_size) + array.shape[axis+1:]
    strides = array.strides[:axis] + (array.strides[axis],) + array.strides[axis:]
    rolled = np.lib.stride_tricks.as_strided(array, shape=shape, strides=strides)
    return np.take(rolled, np.arange(0,shape[axis],freq), axis=axis)

創建測試以斷言 function 有效性的示例:

    arr = np.random.randint(1, 1000, size=(2,108,21,5))
    arr_windowed = rolling_window_ndimensional(arr, 12, 12, axis=1)

    print(arr.shape)
    print(arr_windowed.shape)
    np.allclose(arr, arr_windowed.reshape(2,-1, 21,5))

暫無
暫無

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

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