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

如何为Pandas多层索引DataFrame新增表头层级并调整GM表头位置

Pandas多层索引表头调整问题

初始问题

我有如下Pandas DataFrame:

from collections import defaultdict
import pandas as pd

dic = {'US':{'Quality':{'points':"-2 n", 'difference':'equal', 'stat': 'same'}, 'Prices':{'points':"-7 n", 'difference':'negative', 'stat': 'below'}, 'Satisfaction':{'points':"3 n", 'difference':'positive', 'stat': 'below'}},
      'UK': {'Quality':{'points':"3 n", 'difference':'equal', 'stat': 'above'}, 'Prices':{'points':"-13 n", 'difference':'negative', 'stat': 'below'}, 'Satisfaction':{'points':"2 n", 'difference':'negative', 'stat': 'same'}}}
d1 = defaultdict(dict)
for k, v in dic.items():
    for k1, v1 in v.items():
        for k2, v2 in v1.items():
            d1[(k, k2)].update({k1: v2})

df = pd.DataFrame(d1)

df.columns = df.columns.rename("Skateboard", level=0)
df.columns = df.columns.rename("Q3", level=1)
df.insert(loc=0, column=('', 'Mode'), value="Website")

当前DataFrame样式:列层级为(Skateboard, Q3),首列是('', 'Mode'),内容为"Website",后续列按US、UK下的points/difference/stat展开。

需求:为多层索引DataFrame新增一层表头,使GM作为顶层表头对应points列,其余列对应空顶层表头,且GM表头位于US、UK列组的最前方(每个国家列组的第一部分是GM对应的points列,之后是其余指标列)。

更新后的尝试

我尝试了以下代码:

from collections import defaultdict
import pandas as pd

dic = {'US':{'Quality':{'points':"-2 n", 'difference':'equal', 'stat': 'same'}, 'Prices':{'points':"-7 n", 'difference':'negative', 'stat': 'below'}, 'Satisfaction':{'points':"3 n", 'difference':'positive', 'stat': 'below'}},
      'UK': {'Quality':{'points':"3 n", 'difference':'equal', 'stat': 'above'}, 'Prices':{'points':"-13 n", 'difference':'negative', 'stat': 'below'}, 'Satisfaction':{'points':"2 n", 'difference':'negative', 'stat': 'same'}}}
d1 = defaultdict(dict)
for k, v in dic.items():
    for k1, v1 in v.items():
        for k2, v2 in v1.items():
            d1[(k, k2)].update({k1: v2})

df = pd.DataFrame(d1)

df.columns = df.columns.rename("Skateboard", level=0)
df.columns = df.columns.rename("Metric", level=1)
df1 = df.xs('points', axis=1, level=1, drop_level=False)
df2 = df.drop('points', axis=1, level=1)
df3 = (pd.concat([df1, df2], keys=['GM', ''], axis=1)
 .swaplevel(0, 1, axis=1)
 .sort_index(axis=1))
df3.columns = df3.columns.rename("Q3", level=1)
df3.insert(loc=0, column=('','', 'Mode'), value="Website")

df3

当前DataFrame样式:顶层表头GM和空值被分散在各国家列组中,而非每个国家列组的最前方。

问题:如何将GM表头移动到US和UK列组的最前面,达到目标样式?

解决方案

方法1:调整排序层级优先级

在生成拼接后的DataFrame时,修改排序逻辑,让国家(Skateboard)优先,再按顶层表头(GM优先)排序,最后按指标列排序:

# 重新生成df3并调整排序
df3 = (pd.concat([df1, df2], keys=['GM', ''], axis=1)
       .swaplevel(0, 1, axis=1)
       # 指定排序层级顺序:先国家,再顶层表头(GM在前),最后指标
       .sort_index(axis=1, level=['Skateboard', 0, 'Metric']))

# 重命名列层级
df3.columns = df3.columns.rename(["Skateboard", "TopHeader", "Metric"])
# 插入Mode列
df3.insert(loc=0, column=('', '', 'Mode'), value="Website")

方法2:按国家分组重组列

手动为每个国家组拼接GM列和其余列,确保GM列在每个国家组的最前方:

# 按国家分组处理列
country_groups = []
for country in ['US', 'UK']:
    # 提取当前国家的GM对应列(points)
    gm_cols = df.xs((country, 'points'), axis=1, level=[0,1], drop_level=False)
    # 提取当前国家的非GM列
    other_cols = df.xs(country, axis=1, level=0).drop('points', axis=1)
    
    # 为GM列添加顶层表头标识,其余列添加空表头
    gm_cols.columns = pd.MultiIndex.from_tuples([('GM', country, 'points')], names=['TopHeader', 'Skateboard', 'Metric'])
    other_cols.columns = pd.MultiIndex.from_tuples([('', country, col) for col in other_cols.columns], names=['TopHeader', 'Skateboard', 'Metric'])
    
    # 拼接当前国家的GM列和其余列
    country_groups.append(pd.concat([gm_cols, other_cols], axis=1))

# 拼接所有国家组,插入Mode列
df_final = pd.concat(country_groups, axis=1)
df_final.insert(loc=0, column=('', '', 'Mode'), value="Website")

两种方法都能实现每个国家列组最前方展示GM对应的points列,后续排列其余指标列的目标样式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:10:16