pd.get_dummies() 不支持多标签直接编码,必须先用 explode 展开 list 列为行级结构,再 get_dummies,最后 groupby.sum() 聚合;否则会将整个列表当字符串处理,生成错误列名和数据错位。

直接说结论:pd.get_dummies() 本身不支持多标签(multi-label)场景下的原子级展开——它会把整个列表当字符串处理,导致错误的列名和数据错位。必须先将多标签字段“炸开”成行级结构,再用 get_dummies()。
为什么直接对 list 类型列调用 get_dummies 会失败
假设你有一列 genres,值是 ['action', 'comedy'] 这样的 list。Pandas 默认把它当做一个不可拆分的对象,get_dummies(df['genres']) 实际上会对每个 list 整体做哈希或 str() 转换,生成类似 ['action', 'comedy']、['drama'] 这样的列名,完全不是你想要的 one-hot 效果。
常见错误现象包括:
- 生成列名带方括号和引号,如
"['action', 'comedy']" - 每行只在“原始 list 全貌”那一列置 1,其余全为 0
- 内存暴涨(因 unique list 组合爆炸)
正确做法:先 explode 再 get_dummies
核心步骤是把 list 列“纵向展开”,让每个标签独占一行,再横向 one-hot 编码。这是唯一可靠路径。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 确保目标列是 list 类型,不是字符串(比如从 CSV 读入后需用
ast.literal_eval转回 list) - 用
df.explode('genres')把genres列炸开,原行数 × 平均标签数 - 再对炸开后的列做
pd.get_dummies(df_exploded['genres'], prefix='genre') - 最后用
groupby(..., as_index=False).sum()按原始索引聚合回原行维度
示例片段:
import pandas as pd
df = pd.DataFrame({'id': [1, 2], 'genres': [['action', 'comedy'], ['drama']]})
df_exploded = df.explode('genres')
dummies = pd.get_dummies(df_exploded['genres'], prefix='genre')
result = pd.concat([df_exploded[['id']], dummies], axis=1).groupby('id', as_index=False).sum()
注意 label 顺序、缺失值和稀疏性
explode 后若某行原值是 None 或空 list,explode 会产出 NaN 行,get_dummies 默认跳过 NaN —— 所以最终该行所有 dummy 列都是 0,符合预期。但要注意:
- 如果想保留原始行数(含全零行),
groupby(...).sum()是安全的;用.max()也行,但语义更清晰的是.sum() - 标签顺序不影响结果,
get_dummies按字母序排序列,如需固定顺序,可传入columns参数显式指定 - 高基数标签(如 >1000 类)会导致宽表爆炸,此时应考虑用
sparse=True或转向scikit-learn的MultiLabelBinarizer
真正容易被忽略的是:炸开 + 聚合这一步无法绕过,哪怕你用 apply(pd.Series) 或 str.get_dummies(sep=','),底层仍是模拟 explode 行为。别试图跳过 explode —— 它不是冗余步骤,而是语义正确的必要转换。


















