如何使用nans规范化pandas列的zscore?

时间:2014-05-04 00:23:19

标签: python numpy pandas scipy

我有一个pandas数据框,其中包含一些我希望zscore规范化的实数值:

>> a
array([    nan,  0.0767,  0.4383,  0.7866,  0.8091,  0.1954,  0.6307,
        0.6599,  0.1065,  0.0508])
>> df = pandas.DataFrame({"a": a})

问题是单个nan值会使所有数组nan

>> from scipy.stats import zscore
>> zscore(df["a"])
array([ nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan,  nan])

zscore(或不是scipy的等效函数)应用于pandas数据帧的列并使其忽略nan值的正确方法是什么?我希望它与原始列具有相同的维度,np.nan用于无法规范化的值

修改:也许最好的解决方案是使用scipy.stats.nanmeanscipy.stats.nanstd?我不明白为什么std为此目的需要更改自由度:

zscore = lambda x: (x - scipy.stats.nanmean(x)) / scipy.stats.nanstd(x)

4 个答案:

答案 0 :(得分:19)

pandas'mean的{​​{1}}版本会传递std,因此您可以按照这种方式进行计算(与scipy zscore相同,我认为您需要在Nan上使用ddof = 0):

std

答案 1 :(得分:4)

您可以使用isnan忽略nans。

z = a                    # initialise array for zscores
z[~np.isnan(a)] = zscore(a[~np.isnan(a)])
pandas.DataFrame({'a':a,'Zscore':z})

     Zscore       a
0       NaN     NaN
1 -1.148329  0.0767
2  0.071478  0.4383
3  1.246419  0.7866
4  1.322320  0.8091
5 -0.747912  0.1954
6  0.720512  0.6307
7  0.819014  0.6599
8 -1.047803  0.1065
9 -1.235699  0.0508

答案 2 :(得分:1)

我不确定此参数何时存在,因为我已经很长时间没有使用python了。但是您可以简单地使用参数 nan_policy ='omit',而在计算中会忽略nans:

a = np.array([np.nan,  0.0767,  0.4383,  0.7866,  0.8091,  0.1954,  0.6307, 0.6599, 0.1065,  0.0508])
ZScore_a = stats.zscore(a,nan_policy='omit')

print(ZScore_a)
[nan -1.14832945  0.07147776  1.24641928  1.3223199  -0.74791154
0.72051236  0.81901449 -1.0478033  -1.23569949]

答案 3 :(得分:0)

此问题的另一种替代解决方案是在计算z分数时用列均值填充DataFrame中的NaN。这将导致NaN的z分数被计算为0,然后可以使用原始df上的notna将其屏蔽掉。

您可以创建与原始df尺寸相同的DataFrame,并在一行中的同一位置包含原始df值和NaN的z分数:

zscore_df = pd.DataFrame(scipy.stats.zscore(df.fillna(df.mean())), index=df.index, columns=df.columns).where(df.notna())