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

多索引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()

关键修正点说明

  1. 长格式转换:

    • 先用reset_index()把多索引行拆成Momento和Escala列,避免stack层级混淆
    • 用melt()函数将宽格式的统计量列转成长格式,这是pandas处理宽转长的标准方法,比stack更直观不易出错
  2. 绘图优化:

    • 把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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 14:50:28