【发布时间】:2016-09-25 23:19:28
【问题描述】:
我有动力使用 pandas rolling 功能来执行滚动多因素回归(这个问题不是关于滚动多因素回归)。我希望我能够在df.rolling(2) 之后使用apply 并获取结果pd.DataFrame 用.values 提取ndarray 并执行必要的矩阵乘法。结果不是这样。
这是我发现的:
import pandas as pd
import numpy as np
np.random.seed([3,1415])
df = pd.DataFrame(np.random.rand(5, 2).round(2), columns=['A', 'B'])
X = np.random.rand(2, 1).round(2)
物体是什么样子的:
print "\ndf = \n", df
print "\nX = \n", X
print "\ndf.shape =", df.shape, ", X.shape =", X.shape
df =
A B
0 0.44 0.41
1 0.46 0.47
2 0.46 0.02
3 0.85 0.82
4 0.78 0.76
X =
[[ 0.93]
[ 0.83]]
df.shape = (5, 2) , X.shape = (2L, 1L)
矩阵乘法行为正常:
df.values.dot(X)
array([[ 0.7495],
[ 0.8179],
[ 0.4444],
[ 1.4711],
[ 1.3562]])
使用 apply 逐行执行点积的行为符合预期:
df.apply(lambda x: x.values.dot(X)[0], axis=1)
0 0.7495
1 0.8179
2 0.4444
3 1.4711
4 1.3562
dtype: float64
Groupby -> Apply 行为符合我的预期:
df.groupby(level=0).apply(lambda x: x.values.dot(X)[0, 0])
0 0.7495
1 0.8179
2 0.4444
3 1.4711
4 1.3562
dtype: float64
但是当我跑步时:
df.rolling(1).apply(lambda x: x.values.dot(X))
我明白了:
AttributeError: 'numpy.ndarray' 对象没有属性 'values'
好的,所以 pandas 在其 rolling 实现中直接使用 ndarray。我可以处理。而不是使用.values 来获取ndarray,让我们尝试一下:
df.rolling(1).apply(lambda x: x.dot(X))
形状 (1,) 和 (2,1) 未对齐:1 (dim 0) != 2 (dim 0)
等等!什么?!
所以我创建了一个自定义函数来查看滚动在做什么。
def print_type_sum(x):
print type(x), x.shape
return x.sum()
然后跑:
print df.rolling(1).apply(print_type_sum)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
<type 'numpy.ndarray'> (1L,)
A B
0 0.44 0.41
1 0.46 0.47
2 0.46 0.02
3 0.85 0.82
4 0.78 0.76
我得到的pd.DataFrame 是一样的,这很好。但它打印出 10 个单维 ndarray 对象。 rolling(2)呢?
print df.rolling(2).apply(print_type_sum)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
<type 'numpy.ndarray'> (2L,)
A B
0 NaN NaN
1 0.90 0.88
2 0.92 0.49
3 1.31 0.84
4 1.63 1.58
同样的事情,期望输出,但它打印了 8 个 ndarray 对象。 rolling 正在为每一列生成长度为 window 的单维 ndarray,而不是我预期的形状为 (window, len(df.columns)) 的 ndarray。
问题是为什么?
我现在没有办法轻松运行滚动多因素回归。
【问题讨论】:
-
这是known issue。我最近问过 Jeff,你可以在 cmets 中看到他的回答!
-
从 Pandas 0.20 开始,最先进的解决方案是什么?似乎已经进行了很多改进。直接使用 rolling().apply() 可以实现 OP 中的目标吗?
标签: python pandas numpy group-by pandas-groupby