如何在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
相关产品推荐
相关产品推荐

