对于可能包含x
的{{1}}到y
范围内的数字列表,如何在0和1之间进行标准化,忽略NaN
值(它们保持不变作为NaN
)。
通常情况下,我会使用NaN
中的MinMaxScaler
(ref page),但这不能处理sklearn.preprocessing
并建议根据平均值或中位数等来估算值。 t提供忽略所有NaN
值的选项。
答案 0 :(得分:11)
考虑pd.Series
s
s = pd.Series(np.random.choice([3, 4, 5, 6, np.nan], 100))
s.hist()
选项1
Min Max Scaling
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()
答案 1 :(得分:4)
这是一种不同的方法,我相信它正确地回答了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']])
答案 2 :(得分:1)
似乎sklearn现在(2020年6月)的行为符合您(和我)的期望: np.nan保持不变。 (主要是从sklearn文档粘贴的副本)
import sklearn
import numpy as np
from sklearn.preprocessing import MinMaxScaler
sklearn.__version__
# '0.23.1'
data = np.array([[-1, 2, 3], [-0.5, 6,3 ], [np.nan, 18, 3 ]])
print(data)
#[[-1. 2. 3. ]
# [-0.5 6. 3. ]
# [ nan 18. 3. ]]
scaler = MinMaxScaler()
data = scaler.fit_transform(data)
print(data)
#[[0. 0. 0. ]
# [1. 0.25 0. ]
# [ nan 1. 0. ]]