Python 应用自定义

Python 应用自定义,python,pandas,apply,Python,Pandas,Apply,我一直在遵循一个类似的答案,但在使用sklearn和rollingapply时,我有一些问题。我正在尝试创建z分数并使用滚动应用进行PCA,但我不断得到“只有长度为1的数组才能转换为Python标量”错误。 按照前面的示例,我创建了一个数据帧 from sklearn.preprocessing import StandardScaler import pandas as pd import numpy as np sc=StandardScaler() tmp=pd.DataFrame(np

我一直在遵循一个类似的答案,但在使用sklearn和rollingapply时,我有一些问题。我正在尝试创建z分数并使用滚动应用进行PCA,但我不断得到
“只有长度为1的数组才能转换为Python标量”错误。

按照前面的示例,我创建了一个数据帧

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'])
如果我使用
滚动
命令:

 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
如何使用sklearn创建自定义滚动函数以先标准化,然后运行PCA

编辑: 我意识到我的问题不太清楚,所以我会再试一次。我想标准化我的值,然后运行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模块都是这样。)我只是想得到解释过的方差,它是一个一维项,但下面的代码返回了一堆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维数组。数组必须至少是二维的


总而言之,我想运行滚动z分数,然后滚动pca输出每次滚动时解释的方差。我有向下滚动的z分数,但没有解释方差。

正如@BrenBarn评论的那样,滚动函数需要将向量减少为单个数字。以下内容相当于您试图做的事情,请帮助我们突出问题所在

zscore = lambda x: (x - x.mean()) / x.std()
tmp.rolling(5).apply(zscore)
(tmp - tmp.rolling(5).mean()) / tmp.rolling(5).std()
zscore
函数中,
x.mean()
减少,
x.std()
减少,但
x
是一个数组。因此,整个东西就是一个数组


解决此问题的方法是对z分数计算中需要滚动的部分执行滚动,而不是对导致问题的部分执行滚动

zscore = lambda x: (x - x.mean()) / x.std()
tmp.rolling(5).apply(zscore)
(tmp - tmp.rolling(5).mean()) / tmp.rolling(5).std()

由于lambda函数中的x表示(滚动)系列/ndarray,因此lambda函数可以这样编码(其中x[-1]表示当前滚动数据点):

然后可以打电话:

tmp.rolling(5).apply(zscore)
还注意到自由度默认为1 in
tmp.rolling(5.std()

为了生成与@piRSquared相同的结果,必须为
x.std()
指定ddof,默认值为0--花了很长时间才弄明白

您希望输出是什么?一个函数应该从一个输入块中产生一个标量值。如果你想在块上做更复杂的操作,你必须“自己滚”。谢谢z-score部分。我试图为PCA部分做类似的事情,但没有成功。lambda会不会因为我做了很多行而不是一行而弄乱PCA?嗨,Jerry,当我尝试你的答案时,我在x[-1]上发现了一个关键错误。x属于pandas.core.series.series类。使用x.values[-1]为我解决了这个问题。