如何获取多层索引DataFrame的列均值并保持列顺序?
多层索引DataFrame按指定索引计算均值并保持列顺序
问题需求
对多层索引的DataFrame,按某一层重复出现的索引值(比如年份)计算各数值列的均值,同时需要保持原有的列顺序。
示例说明
创建示例多层索引DataFrame
import pandas as pd # 创建示例DataFrame df = pd.DataFrame({'A': ['A', 'A', 'A','B', 'B', 'B'], 'B': ['2000','2001','2002','2000','2001','2002'], 'C': [1, 2, 3, 4, 5, 6], 'D': [4, 5, 6, 7, 8, 9]}) # 将A(国家)和B(年份)设置为多层索引 df = df.set_index(['A', 'B'])
目标结果
需要得到以年份为索引,C、D列对应年份所有国家均值的DataFrame:
desired_df = pd.DataFrame({'B': ['2000','2001','2002'], 'C': [2.5, 3.5, 4.5], 'D': [5.5, 6.5, 7.5]})
尝试的方法
使用pivot_table计算均值,但实际处理数据时发现列顺序发生了变化:
desired_df=df.pivot_table(values=df.columns, index='B', aggfunc='mean')
实际数据场景
以下是处理世界银行数据的可复现代码,目标是计算除中国外其他国家的年份均值:
import numpy as np import matplotlib.pyplot as plt import pandas as pd import os import wbdata as wb from sklearn.linear_model import LinearRegression from textwrap import wrap country = ['CHN','DEU','USA','KOR','JPN'] # 定义世界银行指标 indicators={'SE.TER.ENRR' : '高等教育毛入学率(%)', 'SP.URB.TOTL.IN.ZS' : '城市人口占总人口比重(%)', 'IP.JRN.ARTC.SC' : '科技出版物数量', 'IP.PAT.RESD' : '居民专利申请量', 'GB.XPD.RSDV.GD.ZS' : '研发支出占GDP比重(%)', 'BM.KLT.DINV.WD.GD.ZS' : '对外直接投资净流出占GDP比重(%)', 'TX.VAL.TECH.MF.ZS' : '高科技产品出口占制造业出口比重(%)', 'NV.MNF.TECH.ZS.UN' : '中高技术制造业增加值占制造业增加值比重(%)', 'NV.IND.TOTL.ZS' : '工业增加值占GDP比重(%)', 'SP.POP.TOTL':'总人口'} # 获取数据并处理 df=wb.get_dataframe(indicators, country = country) df=df.sort_index() # 计算人均指标 df['人均科技出版物数量']=df['科技出版物数量']/df['总人口'] df['人均居民专利申请量']=df['居民专利申请量']/df['总人口'] # 处理中国数据 df_china = df[df.index.isin(['China'], level=0)] df_china = df_china.reset_index() df_china=df_china.set_index('date') # 指定列顺序 valores =['高等教育毛入学率(%)', '城市人口占总人口比重(%)', '研发支出占GDP比重(%)', '对外直接投资净流出占GDP比重(%)', '高科技产品出口占制造业出口比重(%)', '中高技术制造业增加值占制造业增加值比重(%)', '工业增加值占GDP比重(%)', '人均科技出版物数量', '人均居民专利申请量'] df_china=df_china[valores] # 处理其他国家数据并计算均值(此处pivot_table会改变列顺序) df_resto = df[df.index.isin(['United States','Germany','Japan','Korea, Rep.'], level=0)] df_resto = df_resto.reset_index() df_resto=df_resto.set_index('date') df_resto = df_resto[valores] df_resto=df_resto.pivot_table(values=valores, index='date', aggfunc='mean')
解决方案
方法1:使用groupby(推荐,天然保留列顺序)
groupby会自动保持原DataFrame的列顺序,无需额外处理:
针对示例DataFrame
# 按多层索引中的'B'(年份)分组计算均值 desired_df = df.groupby(level='B').mean()
针对实际数据中的df_resto
如果df_resto是重置索引后的单索引(date为索引):
df_resto = df_resto.groupby('date').mean()
如果df_resto未重置索引,仍是多层索引(国家、date):
df_resto = df_resto.groupby(level='date').mean()
方法2:使用pivot_table后重新指定列顺序
若坚持使用pivot_table,计算完成后通过原列名列表重新排序即可恢复顺序:
针对示例DataFrame
desired_df = df.pivot_table(values=df.columns, index='B', aggfunc='mean')[df.columns]
针对实际数据中的df_resto
df_resto = df_resto.pivot_table(values=valores, index='date', aggfunc='mean')[valores]
内容的提问来源于stack exchange,提问作者Mario Diez Martínez
相关产品推荐
相关产品推荐

