私は同様の答え here を追ってきましたが、sklearnを使用してローリングアプライを行うときにいくつか質問があります。 Zスコアを作成してローリングアプライでPCAを実行しようとしていますが、引き続き'only length-1 arrays can be converted to Python scalars' error.
前の例に従って、データフレームを作成します
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'])
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
このエラーが発生します。ただし、平均および標準偏差のある関数を問題なく作成できます。
def test(df):
return np.mean(df)
tmp.rolling(window=5,center=False).apply(lambda x: test(x))
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
最初に標準化してからPCAを実行するために、sklearnでカスタムローリング関数を作成するにはどうすればよいですか?
編集:私は私の質問が正確に明確ではなかったことに気づいたので、もう一度試してみます。値を標準化してからPCAを実行し、各要因によって説明される分散の量を取得します。ローリングせずにこれを行うことはかなり簡単です。
testing=sc.fit_transform(tmp)
pca=decomposition.pca.PCA() #run pca
pca.fit(testing)
pca.explained_variance_ratio_
array([ 0.50967441, 0.49032559])
転がるときにこの同じ手順を使用することはできません。 @piRSquaredのローリングzscore関数を使用すると、zscoreが得られます。 sklearnのPCAは、ローリングアプライカスタム機能と互換性がないようです。 (実際、これはほとんどのsklearnモジュールの場合だと思います。)1次元の項目である説明された分散を取得しようとしていますが、以下のコードはNaNの束を返します。
def test3(df):
pca.fit(df)
return pca.explained_variance_ratio_
tmp.rolling(window=5,center=False).apply(lambda x: test3(x))
ただし、説明された独自の分散関数を作成できますが、これも機能しません。
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))
このエラーが発生します0-dimensional array given. Array must be at least two-dimensional
。
要約すると、ローリングzスコアを実行し、次に各ロールで説明された分散を出力するローリングpcaを実行したいと思います。私はローリングZスコアを持っていますが、説明された差異はありません。
@BrenBarnがコメントしたように、ローリング関数はベクトルを単一の数に減らす必要があります。以下はあなたがやろうとしていたことと同等であり、問題を強調するのに役立ちます。
_zscore = lambda x: (x - x.mean()) / x.std()
tmp.rolling(5).apply(zscore)
_
_TypeError: only length-1 arrays can be converted to Python scalars
_
zscore
関数では、x.mean()
は減少し、x.std()
は減少しますが、x
は配列です。したがって、全体が配列になります。
これを回避する方法は、問題を引き起こす部分ではなく、それを必要とするzスコア計算の部分でロールを実行することです。
_(tmp - tmp.rolling(5).mean()) / tmp.rolling(5).std()
_