如何在Dask中对逗号分隔列实现Dummy/One Hot编码功能?
Dask多值分隔列生成哑变量的实现方案
首先可以明确:原帖说不存在可实现方案的说法是错误的,尤其是你已经提前拿到全量类别列表的场景下,可以非常简单地实现和pd.get_dummies、MultiLabelBinarizer完全对齐的效果。
实现核心逻辑是利用Dask的map_partitions方法,对每个分区的pandas子数据框单独做哑变量转换,因为全量类别已知,所有分区的输出列结构完全一致,不会出现分区之间列不对齐的问题。
完整实现示例
假设待处理的Dask数据框名为ddf,存储多值类别的列名为tag_col,你提前获取的全量类别列表为all_categories,多值之间用逗号分隔:
1. 定义单分区转换函数
import pandas as pd def multi_label_dummies(partition, col_name, all_cats, sep=","): # 拆分多值列,空值按空列表处理 split_vals = partition[col_name].str.split(sep).fillna("") # 初始化全0哑变量表,直接对齐全量类别 dummies = pd.DataFrame(0, index=partition.index, columns=all_cats, dtype="int8") # 遍历填充存在的类别 for idx, vals in split_vals.items(): for v in vals: if v in all_cats: dummies.loc[idx, v] = 1 # 可根据需求选择是否保留原表其他列,这里默认拼接返回 return pd.concat([partition, dummies], axis=1)
2. 应用到全量Dask数据框
import dask.dataframe as dd # 手动指定输出的meta结构,避免Dask自动推断出错 output_meta = ddf._meta.join(pd.DataFrame(columns=all_categories, dtype="int8")) # 执行分区转换 ddf_with_dummies = ddf.map_partitions( multi_label_dummies, col_name="tag_col", all_cats=all_categories, sep=",", meta=output_meta )
无预存全量类别的处理方式
如果你没有提前拿到全量类别列表,也可以先做一次全表扫描拿到所有唯一类别,再执行上述转换即可,仅多一次全量计算的开销,并非无法实现:
# 先计算全量唯一类别列表 all_categories = ddf["tag_col"].str.split(",").explode().unique().compute()
生成的哑变量结果和pandas原生pd.get_dummies、sklearn的MultiLabelBinarizer输出完全一致,不会出现结果偏差。
内容的提问来源于stack exchange,提问作者jxo
相关产品推荐
相关产品推荐

