Нормализовать между 0 и 1, игнорируя NaN

Для списка чисел от x до y, который может содержать NaN, как я могу нормализовать между 0 и 1, игнорируя значения NaN (они остаются как NaN).

Обычно я использовал MinMaxScaler (ref page) из sklearn.preprocessing, но это не может обрабатывать NaN и рекомендует вменять значения основанный на среднем или среднем и т.д., он не предлагает игнорировать все значения NaN.

Ответ 1

рассмотрим pd.Series s

s = pd.Series(np.random.choice([3, 4, 5, 6, np.nan], 100))
s.hist()

введите описание изображения здесь


Вариант 1
Минимальное масштабирование

new = s.sub(s.min()).div((s.max() - s.min()))
new.hist()

введите описание изображения здесь


НЕ ЧТО ОПАСНО ДЛЯ
Я положил их, потому что я хотел

Вариант 2
сигмовидной

sigmoid = lambda x: 1 / (1 + np.exp(-x))

new = sigmoid(s.sub(s.mean()))
new.hist()

введите описание изображения здесь


Вариант 3
tanh (гиперболический тангенс)

new = np.tanh(s.sub(s.mean())).add(1).div(2)
new.hist()

введите описание изображения здесь

Ответ 2

Здесь другой подход и тот, который, как я считаю, правильно отвечает OP, единственная разница заключается в том, что это работает для данных, а не списка, вы можете легко поместить свой список в фреймворк данных, как показано ниже. Другие варианты не работали для меня, потому что мне нужно было хранить MinMaxScaler, чтобы преобразовать преобразование после того, как было сделано предсказание. Поэтому вместо передачи всего столбца в MinMaxScaler вы можете отфильтровать NaN как для цели, так и для ввода.

Пример решения

import pandas as pd

import numpy as np

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler(feature_range=(0, 1))

d = pd.DataFrame({'A': [0, 1, 2, 3, np.nan, 3, 2]})

null_index = d['A'].isnull()

d.loc[~null_index, ['A']] = scaler.fit_transform(d.loc[~null_index, ['A']])