多索引DataFrame可视化报错:如何绘制测试指标随时间的变化趋势图
多索引DataFrame可视化报错:如何绘制测试指标随时间的变化趋势图
嘿,我看了你遇到的问题——用多索引DataFrame绘制测试指标随时间变化的趋势图时一直报错,我来帮你梳理下问题出在哪,以及怎么解决!
问题核心分析
你在将宽格式的统计DataFrame转成**长格式(long format)**时,层级处理出错了,导致后续绘图时无法正确匹配列名。咱们先拆解下你的数据结构:
- 原始
df_stats的行索引是二元组:比如('línea Base', 'Autocompasión'),对应「时间点(Momento)」和「测试维度(Escala)」 - 列是各类统计量:
Mínimo、Promedio等
你用stack(level=0)转格式的方式搞反了层级,导致后续的列名赋值完全错误,这就是绘图时抛出错误的根本原因。
修正方案:正确转换长格式+绘图
下面是修正后的完整代码,我会加上详细注释:
import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt # (你的原始统计字典代码保持不变) # Crear un diccionario para almacenar las estadísticas estadisticas = { 'Mínimo': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].min().min(), ('línea Base', 'Burnout'): df[columnas_burnout_1].min().min(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].min().min(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].min().min(), ('3 meses', 'Burnout'): df[columnas_burnout_2].min().min(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].min().min(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].min().min(), ('6 meses', 'Burnout'): df[columnas_burnout_3].min().min(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].min().min() }, 'Promedio': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].mean().mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].mean().mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].mean().mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].mean().mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].mean().mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].mean().mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].mean().mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].mean().mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].mean().mean() }, 'Desviación Típica': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].std().mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].std().mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].std().mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].std().mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].std().mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].std().mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].std().mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].std().mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].std().mean() }, 'Percentil 25': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].quantile(0.25).mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].quantile(0.25).mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].quantile(0.25).mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].quantile(0.25).mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].quantile(0.25).mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].quantile(0.25).mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].quantile(0.25).mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].quantile(0.25).mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].quantile(0.25).mean() }, 'Mediana': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].median().mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].median().mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].median().mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].median().mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].median().mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].median().mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].median().mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].median().mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].median().mean() }, 'Percentil 75': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].quantile(0.75).mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].quantile(0.75).mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].quantile(0.75).mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].quantile(0.75).mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].quantile(0.75).mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].quantile(0.75).mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].quantile(0.75).mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].quantile(0.75).mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].quantile(0.75).mean() }, 'Máximo': { ('línea Base', 'Autocompasión'): df[columnas_autocompasion_1].max().mean(), ('línea Base', 'Burnout'): df[columnas_burnout_1].max().mean(), ('línea Base', 'Apoyo Social'): df[columnas_apoyo_social_1].max().mean(), ('3 meses', 'Autocompasión'): df[columnas_autocompasion_2].max().mean(), ('3 meses', 'Burnout'): df[columnas_burnout_2].max().mean(), ('3 meses', 'Apoyo Social'): df[columnas_apoyo_social_2].max().mean(), ('6 meses', 'Autocompasión'): df[columnas_autocompasion_3].max().mean(), ('6 meses', 'Burnout'): df[columnas_burnout_3].max().mean(), ('6 meses', 'Apoyo Social'): df[columnas_apoyo_social_3].max().mean() } } # Crear el DataFrame con MultiIndex en las filas df_stats = pd.DataFrame(estadisticas) # --- 修正:正确转换为长格式 --- # 1. 先把多索引的行转成普通列(level_0=Momento, level_1=Escala) df_reset = df_stats.reset_index() df_reset.columns = ['Momento', 'Escala', 'Mínimo', 'Promedio', 'Desviación Típica', 'Percentil 25', 'Mediana', 'Percentil 75', 'Máximo'] # 2. 使用melt将统计量列转成长格式,得到需要的4列 df_long = df_reset.melt( id_vars=['Momento', 'Escala'], # 保留的标识列 var_name='Estadística', # 统计量列的新列名 value_name='Valor' # 对应数值的列名 ) # --- 修正后的绘图代码 --- # 用FacetGrid按统计量分多行,不同时间点用颜色区分 g = sns.FacetGrid(df_long, row='Estadística', hue='Momento', aspect=2, height=4) # 用lineplot更适合展示趋势(如果要散点可以换回scatterplot) g.map(sns.lineplot, 'Escala', 'Valor', marker='o').add_legend() # 设置子图标题和坐标轴标签 g.set_titles("{row_name}") g.set_axis_labels("Escala de Evaluación", "Valor Estadístico") # 调整子图间距避免重叠 plt.tight_layout() plt.show()
关键修正点说明
长格式转换:
- 先用
reset_index()把多索引行拆成Momento和Escala列,避免stack层级混淆 - 用
melt()函数将宽格式的统计量列转成长格式,这是pandas处理宽转长的标准方法,比stack更直观不易出错
- 先用
绘图优化:
- 把
scatterplot换成lineplot+marker='o',更适合展示随时间的趋势变化(如果坚持用散点也可以改回去) - 调整了坐标轴标签的描述,让图表更易读
- 增加
plt.tight_layout()避免子图标题和坐标轴标签重叠
- 把
额外提醒
- 确保你定义的
columnas_autocompasion_1、columnas_burnout_1等变量是正确的列名列表,没有拼写错误或列不存在的情况 - 如果想按时间顺序展示(línea Base → 3 meses → 6 meses),可以把
Momento列转成有序分类:
这样绘图时颜色和图例的顺序会和时间顺序一致。df_long['Momento'] = pd.Categorical( df_long['Momento'], categories=['línea Base', '3 meses', '6 meses'], ordered=True )
备注:内容来源于stack exchange,提问作者Josekawa
相关产品推荐
相关产品推荐

