mi hanno spinto ad utilizzare panda rolling
funzione per eseguire un rotolamento di regressione a più fattori (Questa domanda è NON su rolling regressione a più fattori). Mi aspettavo che sarei stato in grado di usare apply
dopo un df.rolling(2)
e prendere il risultato pd.DataFrame
estrarre il narray con .values
ed eseguire la moltiplicazione della matrice richiesta. Non ha funzionato in questo modo.Perché panda rotolamento dimensione singola uso ndarray
Ecco cosa ho trovato:
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)
Cosa fanno gli oggetti assomigliano:
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)
moltiplicazione di matrici si comporta normalmente:
df.values.dot(X)
array([[ 0.7495],
[ 0.8179],
[ 0.4444],
[ 1.4711],
[ 1.3562]])
Utilizzando applicare per eseguire riga per dot fila il prodotto si comporta come previsto:
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 -> Applica si comporta come ci si aspetterebbe:
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
Ma quando ho eseguito:
df.rolling(1).apply(lambda x: x.values.dot(X))
ottengo:
AttributeError: 'numpy.ndarray' object has no attribute 'values'
Ok, quindi è panda utilizzando direttamente ndarray
all'interno dell'implementazione rolling
. Posso gestirlo. Invece di usare .values
per ottenere il ndarray
, proviamo:
df.rolling(1).apply(lambda x: x.dot(X))
shapes (1,) and (2,1) not aligned: 1 (dim 0) != 2 (dim 0)
Aspetta! Che cosa?!
Così ho creato una funzione personalizzata per vedere cosa sta facendo il rotolamento.
def print_type_sum(x):
print type(x), x.shape
return x.sum()
poi corse:
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
mio risultante pd.DataFrame
è lo stesso, questo è un bene. Ma ha stampato 10 oggetti monodimensionali ndarray
. Che dire 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
Stessa cosa, si aspettano l'uscita ma è stampato 8 ndarray
oggetti. rolling
produce una singola dimensione ndarray
di lunghezza window
per ogni colonna rispetto a quello che mi aspettavo che era uno di forma (window, len(df.columns))
.
La domanda è: perché?
Ora non ho un modo per eseguire facilmente una regressione a più fattori a rotazione.
Si tratta di un [problema noto] (http: // stackoverflow.com/a/21026837/5276797). Di recente ho chiesto a Jeff, puoi leggere la sua risposta nei commenti! – IanS
Qual è la soluzione allo stato dell'arte di Pandas 0.20? Sembra che siano stati fatti molti miglioramenti. L'obiettivo in OP è raggiungibile usando rolling(). Apply() direttamente? – Zhang18