Как 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)
Ответы
Ответ 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