应用滚动窗口并将堆叠的特征向量作为DataFrame返回

时间:2017-09-04 12:36:01

标签: python pandas numpy

是否可以通过应用滚动窗口将系列转换为数据框,计算特征向量并将其作为结果数据框的行?

对于下面的示例,如果我使用apply(),我只能返回float,这将导致另一个已转换的系列。但是,我想计算,例如fft并将每个fft结果堆叠到每个时间步的数据框中,我移动滚动窗口。

import numpy as np
import pandas as pd
import seaborn as sns

N = 1000
ls = np.linspace(0, 2*np.pi, N)
s = np.sin(10*ls) + np.sin(2*ls) + np.sin(6*ls) + 0.2*np.random.rand(N)

df = pd.DataFrame(s, columns=['signal'])

def my_fft(s):
    return np.abs(np.fft.fft(s))[:int(len(s)/2)]

# This works but it feels like a hack ..
l = list()

def test(x):
    l.append(my_fft(x.copy()))
    return np.sum(x)

df.signal.rolling(100).apply(lambda x: test(x))

df_fft = pd.DataFrame(l).T

sns.heatmap(df_fft)

df_fft在每一行中都有相应窗口的FFT结果。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

在我看来,这是大熊猫的缺陷。问题是func

DataFrame.rolling.apply参数
  

必须从ndarray输入中生成单个值

下面的NumPy实现将通过扩展输入数组a的维度来推动窗口滚动。如果传递具有形状(1000,)的df.signal并指定窗口为100,则会得到形状为(901,100)的结果,或者每个长度为100的901个窗口。它已经在Stack Overflow上漂浮了一段时间,我在下面稍作修改。

def rolling_windows(a, window):    
    if window > a.shape[0]:
        raise ValueError('Specified `window` length of {0} exceeds length of'
                         ' `a`, {1}.'.format(window, a.shape[0])) 
    if isinstance(a, (Series, DataFrame)):
        a = a.values
    if a.ndim == 1:
        a = a.reshape(-1, 1)
    shape = (a.shape[0] - window + 1, window) + a.shape[1:]
    strides = (a.strides[0],) + a.strides
    windows = np.squeeze(np.lib.stride_tricks.as_strided(a, shape=shape, 
                                                         strides=strides))
    # In cases where window == len(a), we actually want to "unsqueeze" to 2d.
    #     I.e., we still want a "windowed" structure with 1 window.
    if windows.ndim == 1:
        windows = np.atleast_2d(windows)
    return windows

然后,您可以对结果使用np.apply_along_axis。完全披露,你可以从技术上称之为一个美化的for循环,但它往往很快。

用你的例子:

# np.random.seed(123)
df_fft = np.apply_along_axis(my_fft, 1, rolling_windows(df.signal, window=100))
df_fft = pd.DataFrame(df_fft, index=df.index[100-1:])
# df_fft.shape == (901, 50)