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

使用Plotly.graph_objects制作带滑块的新冠数据堆叠水平柱状图问题求助

解决方案

问题根因

  • 第一个问题:循环内重复创建go.Figure对象,之前月份的trace会被覆盖,最终仅保留最后一个月的2条数据(女性、男性各1条),所以滑块仅显示2个步骤
  • 第二个问题:滑块切换逻辑错误,每个步骤仅单条trace可见,缺少堆叠需要的2条数据,且未全局固定堆叠模式,导致堆叠效果消失

修复后完整代码

import pandas as pd
import plotly.graph_objects as go
from pandas import Timestamp

# 构造示例数据集
df = pd.DataFrame({'index': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
 'columns': ['Fecha', 'Edad', 'Sexo', 'Casos', 'Mes-Año'],
 'data': [[Timestamp('2020-03-31 00:00:00'),'20 - 30','FEMENINO',4,'Mar-20'],
  [Timestamp('2020-03-31 00:00:00'), '20 - 30', 'MASCULINO', 5, 'Mar-20'],
  [Timestamp('2020-03-31 00:00:00'), '30 - 40', 'FEMENINO', 2, 'Mar-20'],
  [Timestamp('2020-03-31 00:00:00'), '30 - 40', 'MASCULINO', 8, 'Mar-20'],
  [Timestamp('2020-04-30 00:00:00'), '20 - 30', 'FEMENINO', 26, 'Apr-20'],
  [Timestamp('2020-04-30 00:00:00'), '20 - 30', 'MASCULINO', 59, 'Apr-20'],
  [Timestamp('2020-04-30 00:00:00'), '30 - 40', 'FEMENINO', 57, 'Apr-20'],
  [Timestamp('2020-04-30 00:00:00'), '30 - 40', 'MASCULINO', 129, 'Apr-20'],
  [Timestamp('2020-05-31 00:00:00'), '20 - 30', 'FEMENINO', 61, 'May-20'],
  [Timestamp('2020-05-31 00:00:00'), '20 - 30', 'MASCULINO', 92, 'May-20'],
  [Timestamp('2020-05-31 00:00:00'), '30 - 40', 'FEMENINO', 131, 'May-20'],
  [Timestamp('2020-05-31 00:00:00'), '30 - 40', 'MASCULINO', 373, 'May-20'],
  [Timestamp('2020-06-30 00:00:00'), '20 - 30', 'FEMENINO', 93, 'Jun-20'],
  [Timestamp('2020-06-30 00:00:00'), '20 - 30', 'MASCULINO', 121, 'Jun-20'],
  [Timestamp('2020-06-30 00:00:00'), '30 - 40', 'FEMENINO', 190, 'Jun-20'],
  [Timestamp('2020-06-30 00:00:00'), '30 - 40', 'MASCULINO', 426, 'Jun-20'],
  [Timestamp('2020-07-31 00:00:00'), '20 - 30', 'FEMENINO', 91, 'Jul-20'],
  [Timestamp('2020-07-31 00:00:00'), '20 - 30', 'MASCULINO', 117, 'Jul-20'],
  [Timestamp('2020-07-31 00:00:00'), '30 - 40', 'FEMENINO', 192, 'Jul-20'],
  [Timestamp('2020-07-31 00:00:00'), '30 - 40', 'MASCULINO', 382, 'Jul-20'],
  [Timestamp('2020-08-31 00:00:00'), '20 - 30', 'FEMENINO', 85, 'Aug-20'],
  [Timestamp('2020-08-31 00:00:00'), '20 - 30', 'MASCULINO', 148, 'Aug-20'],
  [Timestamp('2020-08-31 00:00:00'), '30 - 40', 'FEMENINO', 197, 'Aug-20'],
  [Timestamp('2020-08-31 00:00:00'), '30 - 40', 'MASCULINO', 338, 'Aug-20']]})
df = pd.DataFrame(df['data'].values, columns=df['columns'])

# 初始化空画布,全局设置堆叠模式
fig = go.Figure(layout=go.Layout(
    xaxis = dict(title=dict(text='Casos Covid-19 Por Edad y Sexo: ',font=dict(size=18))),
    yaxis=dict(tickfont=dict(size=14)),
    barmode='stack' # 全局固定堆叠模式
))

# 获取排序后的月份列表
month_list = pd.DatetimeIndex(df['Fecha']).sort_values().unique()
month_name_list = df['Mes-Año'].sort_values().unique()

# 循环追加所有月份的trace
for dt in month_list:
    df_FEM = df.loc[(pd.DatetimeIndex(df['Fecha']) == dt) & (df['Sexo'] == 'FEMENINO')]
    df_MAS = df.loc[(pd.DatetimeIndex(df['Fecha']) == dt) & (df['Sexo'] == 'MASCULINO')]
    # 追加女性trace
    fig.add_trace(go.Bar(
        x = df_FEM['Casos'], 
        y = df_FEM['Edad'],
        orientation = 'h',
        name = 'FEMENINO',
        text = df_FEM['Casos'], 
        texttemplate = '%{text:,9r}',
        textfont = {'size':18}, 
        textposition ='inside', 
        insidetextanchor ='middle'
    ))
    # 追加男性trace
    fig.add_trace(go.Bar(
        x = df_MAS['Casos'], 
        y = df_MAS['Edad'],
        orientation = 'h',
        name = 'MASCULINO',
        text = df_MAS['Casos'], 
        texttemplate = '%{text:,9r}',
        textfont = {'size':18}, 
        textposition ='inside', 
        insidetextanchor ='middle'
    ))

# 构造滑块步骤
steps = []
total_trace = len(fig.data) # 总trace数 = 月份数 * 2
for idx in range(len(month_list)):
    # 每个月份对应2个trace,下标为idx*2 和 idx*2+1
    visible = [False]*total_trace
    visible[idx*2] = True
    visible[idx*2 + 1] = True
    step = dict(
        method="update",
        args=[
            {"visible": visible},
            {"title": f"Casos Covid-19 Por Edad y Sexo: {month_name_list[idx]}"}
        ]
    )
    steps.append(step)

# 添加滑块配置
sliders = [dict(
    active=0,
    currentvalue={"prefix": "当前月份: "},
    pad={"t": 50},
    steps=steps
)]
fig.update_layout(sliders=sliders)

# 默认显示第一个月的数据
fig.data[2:].visible = False
fig.show()

核心修改点说明

  • 提前初始化全局Figure对象,循环内仅使用add_trace追加数据,不会覆盖之前的trace
  • 每个滑块步骤同时启用对应月份的2条trace(女性、男性),保证堆叠所需的两条数据同时可见
  • barmode='stack'全局设置在layout中,滑块切换时不会丢失堆叠配置
  • 滑块标题同步切换为对应月份名称,交互更友好

内容的提问来源于stack exchange,提问作者David YL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:48:00