Функция np.mean() заполняет массив NaN
data = [[None,4,None,3,4],[2,3,4,5,4]]
data1 = [[None,4,None,4,4],[2,3,4,5,4]]
df = pd.DataFrame(data)
df1 = pd.DataFrame(data1)
def x(x):
return (x-np.mean(x))/(np.max(x)-np.min(x))
norm = df.apply(x, axis=1)
norm2 = df1.apply(x, axis=1)
print(norm)
print(norm2)
Результат:
# data
0 1 2 3 4
0 NaN 0.333333 NaN -0.666667 0.333333
1 -0.533333 -0.200000 0.133333 0.466667 0.133333
# data1
0 1 2 3 4
0 NaN NaN NaN NaN NaN
1 -0.533333 -0.2 0.133333 0.466667 0.133333
Почему все данные во втором примере NaN? У них же одинаковое количество данных, только во втором примере все известные данные 4.
Ответы (1 шт):
В случае, когда max()==min(), знаменатель (np.max(x)-np.min(x)) == 0. Возникает ошибка деления на 0 и вместо числа получается NaN.
Что с этим делать?
Вариант 1 - немного изменить функцию x(), добавив обработку при max()==min(). А именно, например, сделав знаменатель 1. Тогда числитель равен 0 (при max()==min()==x==mean()). Ноль делится на 1, получаем ноль (а там, где были NaN, они останутся). К слову, библиотеку np нет необходимости подключать явно, т.к. метод mean() есть в pandas:
def x(x):
mx, mn = x.agg(('max', 'min'))
if mx == mn:
base = 1
else:
base = mx - mn
return x.sub(x.mean()).div(base)
norm = df.apply(x, axis=1)
norm2 = df1.apply(x, axis=1)
print(norm)
print(norm2)
Получаем на исходных данных:
0 1 2 3 4
0 NaN 0.333333 NaN -0.666667 0.333333
1 -0.533333 -0.200000 0.133333 0.466667 0.133333
0 1 2 3 4
0 NaN 0.0 NaN 0.000000 0.000000
1 -0.533333 -0.2 0.133333 0.466667 0.133333
Вариант2 - я бы предложил уйти от apply() и переписать функцию нормализации так, чтобы подавать на вход сразу весь исходный фрейм, а на выходе получать нормализованный:
def normalize(df):
base = df1.max(axis=1).sub(df1.min(axis=1)).replace(0, 1)
return df.sub(df.mean(axis=1), axis=0).div(base, axis=0)
print(normalize(df))
print(normalize(df1))
На выходе тот же результат
0 1 2 3 4
0 NaN 0.333333 NaN -0.666667 0.333333
1 -0.533333 -0.200000 0.133333 0.466667 0.133333
0 1 2 3 4
0 NaN 0.0 NaN 0.000000 0.000000
1 -0.533333 -0.2 0.133333 0.466667 0.133333