python – 为什么pandas滚动使用单维ndarray
我有动力使用熊猫滚动功能来执行滚动多因素回归(这个问题不是关于滚动多因素回归).我希望我能够在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 – >应用表现如我所料: 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)) 我明白了:
好的,所以pandas在其滚动实现中使用了直接的ndarray.我能解决这个问题.不要使用.values来获取ndarray,让我们尝试: df.rolling(1).apply(lambda x: x.dot(X))
等待!什么?! 所以我创建了一个自定义函数来查看正在进行的操作. 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,) 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对象.滚动怎么样(2) print df.rolling(2).apply(print_type_sum) <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对象.滚动为每列产生一个长度窗口的单维ndarray,而不是我预期的形状ndarray(window,len(df.columns)). 问题是为什么? 我现在没有办法轻松运行滚动多因素回归. 解决方法
使用
strides views concept on dataframe ,这是一个矢量化的方法 –
get_sliding_window(df,2).dot(X) # window size = 2 运行时测试 – In [101]: df = pd.DataFrame(np.random.rand(5,'B']) In [102]: X = np.array([2,3]) In [103]: rolled_df = roll(df,2) In [104]: %timeit rolled_df.apply(lambda df: pd.Series(df.values.dot(X))) 100 loops,best of 3: 5.51 ms per loop In [105]: %timeit get_sliding_window(df,2).dot(X) 10000 loops,best of 3: 43.7 μs per loop 验证结果 – In [106]: rolled_df.apply(lambda df: pd.Series(df.values.dot(X))) Out[106]: 0 1 1 2.70 4.09 2 4.09 2.52 3 2.52 1.78 4 1.78 3.50 In [107]: get_sliding_window(df,2).dot(X) Out[107]: array([[ 2.7,4.09],[ 4.09,2.52],[ 2.52,1.78],[ 1.78,3.5 ]]) 那里有巨大的改进,我希望在更大的阵列上保持显着! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |