应用函数于 pandas DataFrame 的滚动切片。

7

我想计算一个 Nx2 矩阵中取大小为2的滚动窗口所得到的多个 2x2 矩阵的行列式。这里我仅将行列式作为示例函数。通常,我希望对一个通过在较大的数据框上窗口化而得到的数据框应用一个函数。

例如,这是一个单独的 2x2 矩阵,我可以这样计算行列式:

import pandas as pd
import numpy as np

d = pd.DataFrame({
   "X": [1,2],
   "Y": [3,4]
   })
np.linalg.det(d)

现在,我可以通过沿着以下数据框的axis=0滑动大小为2的窗口来形成4个2x2矩阵:

df = pd.DataFrame({
    "A": [1,2,3,4,5],
    "B": [6,7,8,9,10],
  })

看起来像这样:

    A   B
0   1   6
1   2   7
2   3   8
3   4   9
4   5   10

所以我将得到[-5.,-5.,-5.,-5.]

据我所知,pandas.DataFrame.rolling和rolling.apply只能应用于1D向量,而不能应用于数据框?你会怎么做?

4个回答

7
从数据框中提取一个numpy数组:
>>> array = df.values
>>> array
array([[ 1,  6],
       [ 2,  7],
       [ 3,  8],
       [ 4,  9],
       [ 5, 10]])

使用numpy的as_strided函数创建滑动窗口视图:
>>> from numpy.lib.stride_tricks import as_strided

>>> rows, cols = array.shape
>>> row_stride, col_stride = array.strides
>>> windowed_array = as_strided(
...     array,
...     shape=(rows - 2 + 1, 2, cols),
...     strides=(row_stride, row_stride, col_stride))
>>> windowed_array
array([[[ 1,  6],
        [ 2,  7]],

       [[ 2,  7],
        [ 3,  8]],

       [[ 3,  8],
        [ 4,  9]],

       [[ 4,  9],
        [ 5, 10]]])

现在将您的函数应用于生成的数组:
>>> np.linalg.det(windowed_array)
array([-5., -5., -5., -5.])

7
#You can replace np.linalg.det with other functions as you like.
#use apply to get 'A' and 'B' from current row and next row and feed them into the function.
df.apply(lambda x: np.linalg.det(df.loc[x.name:x.name+1, 'A':'B']) if x.name <(len(df)-1) else None,axis=1)

Out[157]: 
0   -5.0
1   -5.0
2   -5.0
3   -5.0
4    NaN
dtype: float64

2

使用列表推导式来进行自己的滚动:

s = pd.Series([np.linalg.det(df.iloc[i:i+2]) for i in range(df.shape[0]-1)])

输出:

0   -5.0
1   -5.0
2   -5.0
3   -5.0
dtype: float64

1

这个问题之前已经被问过了。但是在你的情况下,一个简单的解决方法是:

df['A'] * df['B'].shift(-1) - df['A'].shift(-1) * df['B']

输出:

0   -5.0
1   -5.0
2   -5.0
3   -5.0
4    NaN

1
这种方法肯定比使用apply更快,但OP已经指定他正在寻找一种方法来使rolling().apply()适用于多列数据(而determinant只是一个示例函数)。 - Ken Wei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接