You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在保留多级列结构时对Pandas子列应用get_dummies()

如何在多级列DataFrame中对指定子列做独热编码并保留层级结构

嘿,我明白你遇到的问题了——直接用get_dummies替换原列会因为维度不匹配出NaN,而且还想保留原来的多级列结构对吧?我来给你一步步解决这个问题。

先明确需求和示例

你有一个带多级列的Pandas DataFrame,想把所有第二级为one的列转换成独热编码,同时让编码后的列依然归属于原来的第一层级(比如A、B、C),最终得到像你期望的那种结构。

先回顾下你的示例输入:

import pandas as pd

df = pd.DataFrame({
    ('A','one'):['a','a','b'], 
    ('A','two'):['b','a','a'], 
    ('B','one'):['b','b','a'], 
    ('B','two'):['a','a','a'], 
    ('C','one'):['b','a','b'], 
    ('C','two'):['a','b','a'],
})

输出的初始DataFrame长这样:

A     B     C   
  one two one two one two
0  a   b   b   a   b   a
1  a   a   b   a   a   b
2  b   a   a   a   b   a

你想要的结果是把每个one列拆成对应的独热编码列,比如A下的one变成one_a和one_b,还得留在A的层级下。

你之前的尝试为什么不行?

你试过直接赋值:

df.loc[:, (slice(None),'one')] = pd.get_dummies(df.loc[:, (slice(None),'one')])

结果全是NaN,这很正常——原DataFrame里每个第一层级下只有1个one列,但get_dummies返回的是多列,Pandas没法把多列的值塞进单列的位置,自然就出现缺失值了。而且drop_first=True只能生成一列,不符合你要完整独热向量的需求。

正确的解决方案

我们得换个思路:先把要编码的列提出来处理,调整好多级列结构,再和原DataFrame的其他列合并。

具体代码实现(针对你的示例)

import pandas as pd

# 1. 把所有第二级是'one'的列提取出来
one_subset = df.loc[:, (slice(None), 'one')]

# 2. 生成独热编码,然后把列名改成多级结构
dummies = pd.get_dummies(one_subset, prefix_sep='_')
# 把像"A_one_a"这样的列名拆成('A', 'one_a')的多级元组
dummies.columns = pd.MultiIndex.from_tuples(
    [col.split('_', 1) for col in dummies.columns],
    names=df.columns.names
)

# 3. 去掉原DataFrame里的'one'列,再合并编码后的列
non_one_cols = df.drop(columns='one', level=1)
# 合并后按第一层级排序,再调整列顺序让编码列在前
result = pd.concat([non_one_cols, dummies], axis=1).sort_index(axis=1, level=0)

# 手动调整列顺序匹配你的期望输出(如果需要的话)
result = result[[
    ('A','one_a'), ('A','one_b'), ('A','two'),
    ('B','one_a'), ('B','one_b'), ('B','two'),
    ('C','one_a'), ('C','one_b'), ('C','two')
]]

print(result)

运行后就能得到你想要的输出:

A         B         C       
  one_a one_b two one_a one_b two one_a one_b two
0     1     0   b     0     1   a     0     1   a
1     1     0   a     0     1   a     1     0   b
2     0     1   a     1     0   a     0     1   a

更通用的版本(适配任意数量的第一层级列)

如果你的DataFrame不止A、B、C这几个第一层级列,用下面的代码更省心,不需要手动列名:

import pandas as pd

# 提取要编码的子列
one_subset = df.loc[:, (slice(None), 'one')]

# 生成独热编码并重构多级列
dummies = pd.get_dummies(one_subset, prefix_sep='_')
dummies.columns = pd.MultiIndex.from_tuples(
    [tuple(col.split('_', 1)) for col in dummies.columns],
    names=df.columns.names
)

# 保留非one列
non_one_cols = df.drop(columns='one', level=1)

# 合并并排序列
result = pd.concat([non_one_cols, dummies], axis=1).sort_index(axis=1, level=[0,1])

# 自动调整每组内的顺序:编码列在前,原非one列在后
grouped_cols = []
for group in result.columns.get_level_values(0).unique():
    # 收集当前组的编码列和非编码列
    code_cols = [col for col in result.columns if col[0]==group and col[1].startswith('one_')]
    other_cols = [col for col in result.columns if col[0]==group and not col[1].startswith('one_')]
    grouped_cols.extend(code_cols + other_cols)

result = result[grouped_cols]

print(result)

这个版本会自动识别所有第一层级组,把每个组里的编码列放在前面,原列放在后面,完全不用手动指定。

核心思路总结

  1. 分离处理:先把要编码的列单独提出来,避免直接修改原DataFrame导致维度不匹配。
  2. 重构列结构:把get_dummies生成的扁平列名转换成多级列,确保编码后的列仍属于原层级。
  3. 合并整合:去掉原列,把编码后的列和剩余列合并,再调整顺序达到期望效果。

内容的提问来源于stack exchange,提问作者tog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:12:02