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

如何用Python按条件为多层索引列的DataFrame生成新列?

处理二级索引DataFrame的格式化需求(Pythonic实现)

原始DataFrame

metric         grp        Avg                              P95                     
                           mean     ci_low      ci_up       mean     ci_low      ci_up
0      a     CONTROL   8.202862   8.100596   8.306985  17.122063  16.832979  17.400000
1      a  EXPERIMENT   8.243680   8.141428   8.351050  16.709375  16.383333  17.043500
2      a        diff   0.040819  -0.102122   0.185837  -0.412688  -0.855854   0.050104
3      a    rel_diff   0.005016  -0.012299   0.022944  -0.024022  -0.049377   0.002982
4      b     CONTROL  15.513669  15.316762  15.720606  31.893576  31.357300  32.600350
5      b  EXPERIMENT  15.486001  15.293760  15.672843  31.317389  30.808775  31.839000
6      b        diff  -0.027668  -0.300167   0.251497  -0.576186  -1.450138   0.223063
7      b    rel_diff  -0.001740  -0.019249   0.016368  -0.017967  -0.044785   0.007031  

需求

  • 为每个一级列Avg、P95创建格式为mean [ci_low, ci_up]的新列;
  • 对rel_diff行,将所有列格式化为百分比(如0.005016转为0.5%);
  • 其余行将所有列四舍五入到小数点后三位。

Pythonic实现方案

1. 合并多级列并格式化

利用Pandas的层级列操作和apply函数,一次性完成列合并与条件格式化:

import pandas as pd

# 假设数据已加载为DataFrame df
# 获取一级列的唯一名称
level1_cols = df.columns.get_level_values(0).unique()

# 为每个一级列生成合并后的格式化列
for col in level1_cols:
    # 定位当前一级列下的三个二级列
    mean_col = (col, 'mean')
    ci_low_col = (col, 'ci_low')
    ci_up_col = (col, 'ci_up')
    
    # 定义行级格式化逻辑
    def format_entry(row):
        if row['grp'] == 'rel_diff':
            # 百分比格式化:乘100后保留1位小数
            mean = f"{row[mean_col] * 100:.1f}%"
            ci_low = f"{row[ci_low_col] * 100:.1f}%"
            ci_up = f"{row[ci_up_col] * 100:.1f}%"
        else:
            # 普通行保留3位小数
            mean = f"{row[mean_col]:.3f}"
            ci_low = f"{row[ci_low_col]:.3f}"
            ci_up = f"{row[ci_up_col]:.3f}"
        return f"{mean} [{ci_low}, {ci_up}]"
    
    # 添加新列,列名为一级列名
    df[col] = df.apply(format_entry, axis=1)

# 清理旧的多级列,保留核心列和新生成的格式化列
df = df[['metric', 'grp'] + list(level1_cols)]

2. 单独格式化原数值列(可选)

如果需要保留原数值列并分别格式化,可通过布尔掩码批量处理:

# 定位rel_diff行
rel_diff_mask = df['grp'] == 'rel_diff'

# 提取所有数值列
numeric_cols = df.select_dtypes(include=['float64']).columns

# 批量格式化rel_diff行为百分比
df.loc[rel_diff_mask, numeric_cols] = df.loc[rel_diff_mask, numeric_cols].applymap(
    lambda x: f"{x * 100:.1f}%"
)

# 批量格式化其他行为三位小数
non_rel_diff_mask = ~rel_diff_mask
df.loc[non_rel_diff_mask, numeric_cols] = df.loc[non_rel_diff_mask, numeric_cols].applymap(
    lambda x: f"{x:.3f}"
)

最终效果示例

处理后的DataFrame如下:

metric         grp                Avg                  P95
0      a     CONTROL   8.203 [8.101, 8.307]  17.122 [16.833, 17.400]
1      a  EXPERIMENT   8.244 [8.141, 8.351]  16.709 [16.383, 17.044]
2      a        diff   0.041 [-0.102, 0.186]  -0.413 [-0.856, 0.050]
3      a    rel_diff  0.5% [-1.2%, 2.3%]  -2.4% [-4.9%, 0.3%]
4      b     CONTROL  15.514 [15.317, 15.721]  31.894 [31.357, 32.600]
5      b  EXPERIMENT  15.486 [15.294, 15.673]  31.317 [30.809, 31.839]
6      b        diff  -0.028 [-0.300, 0.251]  -0.576 [-1.450, 0.223]
7      b    rel_diff  -0.2% [-1.9%, 1.6%]  -1.8% [-4.5%, 0.7%]

核心Pythonic特性

  • 使用applymap/apply实现批量元素操作,避免低效的逐行循环;
  • 借助布尔掩码loc精准定位目标行,实现高效条件处理;
  • 利用多级列的get_level_values方法便捷提取层级信息,符合Pandas原生设计;
  • 格式化逻辑封装为轻量函数,保持代码简洁可读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:40:56