Pandas Rolling Apply personalizados

He estado siguiendo una respuesta similar aquí , pero tengo algunas preguntas al usar Sklearn y Rolling. Estoy tratando de crear puntuaciones z y hacer PCA con aplicación de balanceo, pero sigo obteniendo que 'only length-1 arrays can be converted to Python scalars' error.

Siguiendo el ejemplo anterior creo un dataframe

 from sklearn.preprocessing import StandardScaler import pandas as pd import numpy as np sc=StandardScaler() tmp=pd.DataFrame(np.random.randn(2000,2)/10000,index=pd.date_range('2001-01-01',periods=2000),columns=['A','B']) 

Si utilizo el comando rolling :

  tmp.rolling(window=5,center=False).apply(lambda x: sc.fit_transform(x)) TypeError: only length-1 arrays can be converted to Python scalars 

Me sale este error. Sin embargo, puedo crear funciones con desviaciones medias y estándar sin ningún problema.

 def test(df): return np.mean(df) tmp.rolling(window=5,center=False).apply(lambda x: test(x)) 

Creo que el error se produce cuando estoy tratando de restar la media por los valores actuales para la puntuación z.

 def test2(df): return df-np.mean(df) tmp.rolling(window=5,center=False).apply(lambda x: test2(x)) only length-1 arrays can be converted to Python scalars 

¿Cómo puedo crear funciones de laminación personalizadas con sklearn para primero estandarizar y luego ejecutar PCA?

EDIT: Me doy cuenta de que mi pregunta no era exactamente clara, así que lo intentaré de nuevo. Quiero estandarizar mis valores y luego ejecutar PCA para obtener la cantidad de variación explicada por cada factor. Hacer esto sin rodar es bastante sencillo.

 testing=sc.fit_transform(tmp) pca=decomposition.pca.PCA() #run pca pca.fit(testing) pca.explained_variance_ratio_ array([ 0.50967441, 0.49032559]) 

No puedo usar este mismo procedimiento al rodar. El uso de la función rolling zscore de @piRSquared da los zscores. Parece que PCA de sklearn es incompatible con la función personalizada Rolling. (De hecho, creo que este es el caso con la mayoría de los módulos de Sklearn). Solo estoy tratando de obtener la varianza explicada que es un elemento unidimensional, pero este código a continuación devuelve un montón de NaN.

 def test3(df): pca.fit(df) return pca.explained_variance_ratio_ tmp.rolling(window=5,center=False).apply(lambda x: test3(x)) 

Sin embargo, puedo crear mi propia función de varianza explicada, pero esto tampoco funciona.

 def test4(df): cov_mat=np.cov(df.T) #need covariance of features, not observations eigen_vals,eigen_vecs=np.linalg.eig(cov_mat) tot=sum(eigen_vals) var_exp=[(i/tot) for i in sorted(eigen_vals,reverse=True)] return var_exp tmp.rolling(window=5,center=False).apply(lambda x: test4(x)) 

Me sale este error 0-dimensional array given. Array must be at least two-dimensional 0-dimensional array given. Array must be at least two-dimensional .

Para recapitular, me gustaría ejecutar z-scores y luego roll pca dando salida a la varianza explicada en cada tirada. Tengo los puntajes z descendentes pero no la varianza explicada.

Como comentó @BrenBarn, la función de desplazamiento necesita reducir un vector a un solo número. Lo siguiente es equivalente a lo que intentaba hacer y la ayuda para resaltar el problema.

 zscore = lambda x: (x - x.mean()) / x.std() tmp.rolling(5).apply(zscore) 
 TypeError: only length-1 arrays can be converted to Python scalars 

En la función zscore , x.mean() reduce, x.std() reduce, pero x es una matriz. Así, todo el asunto es una matriz.


La forma de evitar esto es realizar la tirada en las partes del cálculo de puntuación z que lo requieren, y no en las partes que causan el problema.

 (tmp - tmp.rolling(5).mean()) / tmp.rolling(5).std() 

introduzca la descripción de la imagen aquí