简体   繁体   English

带有Pandas或Numpy的n维滑动窗口

[英]n-dimensional sliding window with Pandas or Numpy

How do I do the R(xts) equivalent of rollapply(...., by.column=FALSE), using Numpy or Pandas? 我如何使用Numpy或Pandas等效于rollapply(....,by.column = FALSE)的R(xts)? When given a dataframe, pandas rolling_apply seems only to work column by column instead of providing the option to provide a full (window-size) x (data-frame-width) matrix to the target function. 给定数据帧时,pandasrolling_apply似乎只能逐列工作,而不是提供向目标函数提供完整(窗口大小)x(数据帧宽度)矩阵的选项。

import pandas as pd
import numpy as np

xx = pd.DataFrame(np.zeros([10, 10]))
pd.rolling_apply(xx, 5, lambda x: np.shape(x)[0]) 

    0   1   2   3   4   5   6   7   8   9
0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4   5   5   5   5   5   5   5   5   5   5
5   5   5   5   5   5   5   5   5   5   5
6   5   5   5   5   5   5   5   5   5   5
7   5   5   5   5   5   5   5   5   5   5
8   5   5   5   5   5   5   5   5   5   5
9   5   5   5   5   5   5   5   5   5   5

So what's happening is rolling_apply is going down each column in turn and applying a sliding 5-length window down each one of these, whereas what I want is for the sliding windows to be a 5x10 array each time, and in this case, I would get a single column vector (not 2d array) result. 因此,发生的情况是rolling_apply依次向下移动每一列,并在每一列中向下滑动一个5长度的窗口,而我想要的是每次滑动窗口为5x10数组,在这种情况下,我将获得单列向量(不是二维数组)结果。

I indeed cannot find a way to compute "wide" rolling application in pandas docs, so I'd use numpy to get a "windowing" view on the array and apply a ufunc to it. 我确实找不到在pandas docs中计算“广泛”滚动应用程序的方法,因此我将使用numpy在数组上获取“窗口”视图并对其应用ufunc。 Here's an example: 这是一个例子:

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

In [41]: win_size = 5

In [42]: isize = arr.itemsize; isize
Out[42]: 8

arr.itemsize is 8 because default dtype is np.int64 , you need it for the following "window" view idiom: arr.itemsize为8,因为默认np.int64np.int64 ,您需要它用于以下“窗口”视图惯用语:

In [43]: windowed = np.lib.stride_tricks.as_strided(arr,
                                                    shape=(arr.shape[0] - win_size + 1, win_size, arr.shape[1]),
                                                    strides=(arr.shape[1] * isize, arr.shape[1] * isize, isize)); windowed
Out[43]: 
array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24]],

       [[ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29]],

       [[10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34]],

       [[15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34],
        [35, 36, 37, 38, 39]],

       [[20, 21, 22, 23, 24],
        [25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34],
        [35, 36, 37, 38, 39],
        [40, 41, 42, 43, 44]],

       [[25, 26, 27, 28, 29],
        [30, 31, 32, 33, 34],
        [35, 36, 37, 38, 39],
        [40, 41, 42, 43, 44],
        [45, 46, 47, 48, 49]]])

Strides are number of bytes between two neighbour elements along given axis, thus strides=(arr.shape[1] * isize, arr.shape[1] * isize, isize) means skip 5 elements when going from windowed[0] to windowed[1] and skip 5 elements when going from windowed[0, 0] to windowed[0, 1]. 步幅是沿给定轴的两个相邻元素之间的字节数,因此strides=(arr.shape[1] * isize, arr.shape[1] * isize, isize)表示从windowed [0]到windowed跳过5个元素[1],并从windowed [0,0]转到windowed [0,1]时跳过5个元素。 Now you can call any ufunc on the resulting array, eg: 现在您可以在结果数组上调用任何ufunc,例如:

In [44]: windowed.sum(axis=(1,2))
Out[44]: array([300, 425, 550, 675, 800, 925])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM