是否可以通过应用滚动窗口将系列转换为数据框,计算特征向量并将其作为结果数据框的行?
对于下面的示例,如果我使用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结果。有更好的方法吗?
答案 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)