por que os pandas rolantes usam o ndarray de dimensão única
Eu estava motivado para usar pandasrolling
para executar uma regressão multifatorial contínua (esta pergunta éNÃO sobre rolagem de regressão multifatorial). Eu esperava que eu fosse capaz de usarapply
após umdf.rolling(2)
e pegue a resultantepd.DataFrame
extrair o ndarray com.values
e execute a multiplicação de matrizes necessária. Não funcionou dessa maneira.
Aqui está o que eu encontrei:
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)
Como são os objetos:
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)
A multiplicação de matrizes se comporta normalmente:
df.values.dot(X)
array([[ 0.7495],
[ 0.8179],
[ 0.4444],
[ 1.4711],
[ 1.3562]])
O uso de apply para executar o produto de linha a linha se comporta conforme o esperado:
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 se comporta como eu esperava:
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
Mas quando eu corro:
df.rolling(1).apply(lambda x: x.values.dot(X))
Eu recebo:
AttributeError: o objeto 'numpy.ndarray' não possui atributos 'valores'
Ok, então os pandas estão usandondarray
dentro do seurolling
implementação. Eu posso cuidar disso. Ao invés de usar.values
para obter ondarray
, vamos tentar:
df.rolling(1).apply(lambda x: x.dot(X))
formas (1,) e (2,1) não alinhadas: 1 (dim 0)! = 2 (dim 0)
Esperar! O que?!
Então, criei uma função personalizada para analisar o que está rolando.
def print_type_sum(x):
print type(x), x.shape
return x.sum()
Então correu:
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
Meu resultantepd.DataFrame
é o mesmo, isso é bom. Mas imprimiu 10 dimensões unidimensionaisndarray
objetos. Sobrerolling(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
A mesma coisa, espera saída, mas imprimiu 8ndarray
objetos.rolling
está produzindo uma única dimensãondarray
de comprimentowindow
para cada coluna, em oposição ao que eu esperava, que era umndarray
de forma(window, len(df.columns))
.
Agora não tenho como executar facilmente uma regressão multifatorial contínua.