LabelEncoder,将缺失值保留为“ NaN”

时间:2019-01-30 15:40:03

标签: python pandas dataframe

我很想在order中使用标签编码器将分类数据转换为数值。

我需要一个LabelEncoder来将丢失的值保留为“ NaN”,以便以后使用Imputer。因此,在像这样标记后

,我想使用掩码替换原始数据框
df = pd.DataFrame({'A': ['x', np.NaN, 'z'], 'B': [1, 6, 9], 'C': [2, 1, np.NaN]})


    A   B   C
0   x   1   2.0
1   NaN 6   1.0
2   z   9   NaN


dfTmp = df
mask = dfTmp.isnull()

       A    B   C
0   False   False   False
1   True    False   False
2   False   False   True

所以我得到一个具有True / false值的数据框

然后,在创建编码器中:

df = df.astype(str).apply(LabelEncoder().fit_transform)

然后,如何编码这些值?

谢谢

1 个答案:

答案 0 :(得分:1)

第一个问题是:您是否希望分别对每一列进行编码或使用一种编码对它们全部进行编码?

表达式df = df.astype(str).apply(LabelEncoder().fit_transform)表示您分别对所有列进行编码。

That case you can do the following:
df = df.apply(lambda series: pd.Series(
    LabelEncoder().fit_transform(series[series.notnull()]),
    index=series[series.notnull()].index
))
print(df)
Out:
     A  B    C
0  0.0  0  1.0
1  NaN  1  0.0
2  1.0  2  NaN

下面是它的工作原理。但是,对于初学者来说,我将介绍该解决方案的一些弊端。

缺点
首先,列的类型多种多样:如果列包含NaN值,则列的类型为float,因为nan在python中是浮点数。

df.dtypes
A    float64
B      int64
C    float64
dtype: object

标签似乎毫无意义。好的,稍后您可以忽略所有的nan,并将其余的隐蔽为整数。

第二点是:可能您需要记住一个LabelEncoder-因为经常需要进行逆变换。但是此解决方案不会记住编码器,您没有这种可变性。

一个简单,明确的解决方案是:

encoders = dict()

for col_name in df.columns:
    series = df[col_name]
    label_encoder = LabelEncoder()
    df[col_name] = pd.Series(
        label_encoder.fit_transform(series[series.notnull()]),
        index=series[series.notnull()].index
    )
    encoders[col_name] = label_encoder

print(df)
Out:
     A  B    C
0  0.0  0  1.0
1  NaN  1  0.0
2  1.0  2  NaN

-更多代码,但结果相同

print(encoders)
Out
{'A': LabelEncoder(), 'B': LabelEncoder(), 'C': LabelEncoder()}

-也可以使用编码器。逆变换(也应该把nan放掉!):

encoders['B'].inverse_transform(df['B'])
Out:
array([1, 6, 9])

此外,还提供了一些选项,例如用于编码器的某些注册表超类,它们与第一个解决方案兼容,但更容易遍历列。

工作原理

df.apply(lambda series: ...)应用一个函数,该函数将pd.Series返回到每一列;因此,它将返回具有新值的数据框。

逐步表达:

pd.Series(
    LabelEncoder().fit_transform(series[series.notnull()]),
    index=series[series.notnull()].index
)

-series[series.notnull()]删除NaN的值,然后将其余的值馈送到fit_transform

--标签编码器返回一个numpy.array并抛出一个索引,index=series[series.notnull()].index将其还原以正确地将其连接起来。如果不做索引:

print(df)
Out:
     A  B    C
0    x  1  2.0
1  NaN  6  1.0
2    z  9  NaN
df = df.apply(lambda series: pd.Series(
    LabelEncoder().fit_transform(series[series.notnull()]),
))
print(df)
Out:
     A  B    C
0  0.0  0  1.0
1  1.0  1  0.0
2  NaN  2  NaN

-值从正确的位置偏移-甚至可能发生IndexError

所有列的单个编码器

在这种情况下,堆叠数据框,拟合编码,然后再将其拆栈

series_stack = df.stack().astype(str)
label_encoder = LabelEncoder()
df = pd.Series(
    label_encoder.fit_transform(series_stack),
    index=series_stack.index
).unstack()
print(df)
Out:
     A    B    C
0  5.0  0.0  2.0
1  NaN  3.0  1.0
2  6.0  4.0  NaN

-因为series_stackpd.Series包含NaN的元素,所以DataFrame中的所有值都是浮点数,因此您可能希望对其进行转换。

希望有帮助。