
本文介绍两种基于 pandas 的高效方法,将 DataFrame 中存储列表的列(如 ['A', 'B'])一键转换为多列独热编码(A/B/C 列取值为 0 或 1),无需循环或手动遍历,兼顾可读性与性能。
本文介绍两种基于 pandas 的高效方法,将 dataframe 中存储列表的列(如 `['a', 'b']`)一键转换为多列独热编码(a/b/c 列取值为 0 或 1),无需循环或手动遍历,兼顾可读性与性能。
在数据预处理中,常遇到某列以 Python 列表形式存储多个类别标签(例如用户兴趣标签、商品多品类归属等)。直接对这类列建模不可行,需先展开为独热编码格式。Pandas 提供了简洁优雅的链式操作方案,核心在于 explode() + 统计聚合 的组合。
以下以示例数据为基准:
import pandas as pd
df = pd.DataFrame({
'id': [1, 2, 3],
'items': [['A', 'B'], ['A', 'B', 'C'], ['A', 'C']]
})
✅ 方法一:pd.crosstab()(推荐 —— 简洁、语义清晰)
利用 explode() 展开列表后,用 crosstab 直接生成交叉频数表,天然适配独热需求(存在即为 1,不存在即为 0):
result = df.merge(
pd.crosstab(*df.explode('items').to_numpy().T)
.reset_index(names='id')
)
print(result)
? 原理说明:
df.explode('items')将每行列表拆为多行 →.to_numpy().T转置为(id_col, items_col)元组 →crosstab自动统计每个id对应各item的出现次数(非 0 即 1)→merge回原表。
✅ 方法二:pivot_table()(灵活、支持扩展)
更显式地控制索引、列与聚合逻辑,适合后续需扩展(如统计频次、加权等)的场景:
result = df.merge(
df.explode('items')
.pivot_table(
index='id',
columns='items',
values='id',
aggfunc='size', # 等价于 len,但更高效
fill_value=0
)
.rename_axis(None, axis=1) # 移除列名 'items'
.reset_index()
)
⚠️ 注意:
aggfunc='size'比len更优(避免空组报错),且fill_value=0确保缺失项补零;rename_axis(None, axis=1)是关键步骤,否则列名会保留items标签,影响后续使用。
? 补充说明与最佳实践
-
性能对比:两种方法在中小规模数据(crosstab 在纯二值场景下语义更精准,
pivot_table更灵活。 -
列名一致性:若原始
items列含重复值(如['A', 'A', 'B']),explode后会生成重复行,此时crosstab和pivot_table(..., aggfunc='size')仍正确计数(可 >1);如严格需要“是否包含”(即 0/1),可追加.clip(upper=1)。 -
缺失值处理:
explode()会自动跳过NaN或空列表([]),如需保留空行,可先用df['items'].apply(lambda x: x if x else ['__MISSING__'])预填充。 -
最终输出结构:结果自动保留原始列(如
id,items),并新增独热列(A,B,C),类型为int64,可直接用于 scikit-learn 等下游模型。
掌握这两种模式,即可从容应对各类嵌套列表型特征的向量化任务——简洁、健壮、符合 pandas 函数式编程范式。










