Подтвердить что ты не робот

Как zscore нормализовать столбец pandas с nans?

У меня есть фреймворк 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 для значений, которые не могут быть нормализованы

edit: возможно, лучшим решением является использование scipy.stats.nanmean и scipy.stats.nanstd? Я не понимаю, почему для этой цели необходимо изменить степень свободы для std:

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

Ответ 1

Ну, версии pandas' mean и std передадут Nan, чтобы вы могли просто вычислить этот путь (чтобы получить то же самое, что и scipy zscore, я думаю, вам нужно использовать ddof = 0 на std):

df['zscore'] = (df.a - df.a.mean())/df.a.std(ddof=0)
print df

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

Ответ 2

Вы можете игнорировать nans, используя isnan.

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