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

如何在Pandas多级索引DataFrame中计算年度差值

问题描述

我有如下DataFrame:

df_test = sns.load_dataset("flights")
df_test['cat_2'] = np.random.choice(range(10), df_test.shape[0])
df_test.pivot_table(index='month', 
                      columns='year', 
                      values=['passengers', 'cat_2'])
                          .swaplevel(0,1, axis=1)
                          .sort_index(axis=1, level=0)
                          .fillna(0)

我想要计算每年的cat_2和passengers与上一年的百分比差值,首年无对比值填充为0。期望输出示例如下:

year    1949                            1950                                1951    
        cat_2   passengers    % diff    cat_2   passengers   % diff         cat_2   passengers     % diff
month                                                                                   
Jan     6       112           0         6       115          115/112        6       90                90/115
Feb     0       118           0         6       126          126/118        6       150               150 / 126  
Mar     2       132           0         7       141                         7       141
Apr     0       129           0         9       135                         9       135
May     5       121           0         4       125                         4       125
Jun     1       135           0         3       149                         3       149
Jul     6       148           0         5       170                         5       170
Aug     5       148           0         2       170                         2       170
Sep     1       136           0         4       158                         4       158
Oct     5       119           0         5       133                         5       133
Nov     0       104           0         1       114                         1       114
Dec     7       118           0         1       140                         1       140

示例仅展示了passengers的计算方式,cat_2需采用相同计算逻辑。

解决方案

可以通过以下步骤实现需求:

  • 生成指定结构的透视表
  • 按年份遍历,对每个指标计算与上一年的百分比差值,首年填充0
  • 处理除零导致的异常值,确保结果合理
  • 将计算结果按多级列格式合并,匹配原表结构

完整代码如下:

import seaborn as sns
import numpy as np
import pandas as pd

# 生成初始数据
df_test = sns.load_dataset("flights")
df_test['cat_2'] = np.random.choice(range(10), df_test.shape[0])

# 创建透视表
pivot_df = df_test.pivot_table(index='month', 
                               columns='year', 
                               values=['passengers', 'cat_2']) \
                  .swaplevel(0, 1, axis=1) \
                  .sort_index(axis=1, level=0) \
                  .fillna(0)

# 获取所有年份列表
years = pivot_df.columns.get_level_values(0).unique()
# 定义需要计算的指标
metrics = ['cat_2', 'passengers']

# 初始化最终结果表
final_df = pd.DataFrame()

for idx, year in enumerate(years):
    # 获取当前年份的指标数据
    current_data = pivot_df[year]
    # 获取上一年数据(首年无,设为None)
    prev_data = pivot_df[years[idx-1]] if idx > 0 else None
    
    # 存储当前年份的所有列数据和列名
    year_cols = []
    year_data = []
    
    for metric in metrics:
        # 添加当前指标值
        year_data.append(current_data[metric])
        year_cols.append((year, metric))
        
        # 计算百分比差值,首年填充0
        if prev_data is not None:
            pct_diff = current_data[metric] / prev_data[metric]
            # 处理除零导致的无穷值,替换为0
            pct_diff = pct_diff.replace([np.inf, -np.inf], 0).fillna(0)
        else:
            pct_diff = pd.Series([0]*len(current_data), index=current_data.index)
        
        year_data.append(pct_diff)
        year_cols.append((year, f'{metric}_%diff'))
    
    # 组合当前年份的DataFrame
    year_df = pd.concat(year_data, axis=1)
    year_df.columns = pd.MultiIndex.from_tuples(year_cols)
    # 合并到最终结果
    final_df = pd.concat([final_df, year_df], axis=1)

# 打印结果
print(final_df)

代码说明

  • 透视表生成后,通过swaplevel和sort_index调整列层级,确保年份为第一级列索引
  • 遍历每个年份时,对cat_2和passengers分别计算与上一年的百分比比值,首年直接填充0
  • 针对cat_2可能出现的上一年为0的情况,用replace处理无穷值,避免报错
  • 最终结果保持多级列结构,每个年份下依次展示指标值和对应的百分比差值

内容的提问来源于stack exchange,提问作者Jonas Palačionis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:30:21