python - 将缺失值保持为“NaN”的 LabelEncoder
问题描述
我正在尝试使用标签编码器将分类数据转换为数值。
我需要一个 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
所以我得到一个具有真/假值的数据框
然后,在创建编码器:
df = df.astype(str).apply(LabelEncoder().fit_transform)
那么我该如何继续,以编码这些值?
谢谢
解决方案
第一个问题是:您希望单独编码每一列还是用一个编码对它们全部编码?
该表达式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
.
- 当标签编码器返回 anumpy.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_stack
包含pd.Series
' NaN
s,DataFrame 中的所有值都是浮点数,因此您可能更喜欢转换它。
希望能帮助到你。
推荐阅读
- c - 信号“自动阻塞”(当执行进入处理函数时)是否会阻止另一个这样的信号被传递到另一个线程?
- android - Android ConstraintLayout : 设计一个适应高度/宽度的自定义键盘
- react-native - 世博会手机摄像头权限窗口在IOS中打不开
- reactjs - 使用自定义 npm 包进行模块解析失败
- graphviz - 点:避免太水平的树
- amazon-s3 - 如何在 PySpark 中测试模拟(moto/boto)S3 读/写
- python - genfromtxt 仅在更改 dtype 后导入第一列
- httprequest - 在zuul过滤器中修改请求头
- automapper - 使用 LightInject 配置 AutoMapper
- java - 在 Junit 中使用 Vert.x 和 PowerMockito 时出现问题