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

Plotly Python交互式绘图实现多项选择展示功能求助

解决方案

原生Plotly的下拉菜单(updatemenus)本身不支持多选操作,针对你的需求有两种可落地的实现方案:


方案1:轻量无额外依赖,用原生图例交互实现多选

这是最适合新手的方案,不用引入新框架,只需要修改原有代码的逻辑缺陷、开启图例交互能力即可,用户可以直接点击图例项切换任意曲线的显示/隐藏,支持同时选中多个。

修改点说明

  • 修复原有代码中button_all重复覆盖、按钮可见性逻辑仅控制真实值曲线、未关联对应预测曲线的问题
  • 给每条trace的名称加上对应项目列名,避免图例重名无法区分
  • 保留原有的全选/单项目切换按钮,额外支持用户自由点击图例多选

修改后代码

import plotly.graph_objects as go

def interactive_multi_plot(actual, forecast_1, forecast_2, title, addAll = True):
    fig = go.Figure()
    # 存储所有trace对应的列名,方便后续按钮控制可见性
    trace_cols = []
    
    # 按项目分组添加三条对应曲线
    for column in actual.columns.to_list():
        # 真实值曲线
        fig.add_trace(
            go.Scatter(
                x = actual.index,
                y = actual[column],
                name = f"{column} - 真实值" 
            )
        )
        trace_cols.append(column)
        # SI预测曲线
        fig.add_trace(
            go.Scatter(
                x = forecast_1.index,
                y = forecast_1[column],
                name = f"{column} - SI预测"
            )
        )
        trace_cols.append(column)
        # LSTM预测曲线
        fig.add_trace(
            go.Scatter(
                x = forecast_2.index,
                y = forecast_2[column],
                name = f"{column} - LSTM预测" 
            )
        )
        trace_cols.append(column)
    
    # 全选按钮逻辑
    button_all = dict(label = '全部',
                  method = 'update',
                  args = [{'visible': [True]*len(trace_cols),
                           'title': '全部',
                           'showlegend':True}])
    
    # 单项目切换按钮逻辑
    def create_layout_button(column):
        # 只有对应列的trace设为可见
        visible = [col == column for col in trace_cols]
        return dict(label = column,
                    method = 'update',
                    args = [{'visible': visible,
                             'title': column,
                             'showlegend': True}])
    
    # 更新布局
    fig.update_layout(
        updatemenus=[go.layout.Updatemenu(
            active = 0,
            buttons = ([button_all] * addAll) +  list(actual.columns.map(lambda column: create_layout_button(column)))
            )
        ],
        # 显式配置图例多选交互规则
        legend=dict(
            itemclick="toggle", # 点击切换当前项显示状态
            itemdoubleclick="toggleothers" # 双击隐藏其他所有项
        ),
        plot_bgcolor = '#010028',
        paper_bgcolor = '#010028',
        title_text=title,
        height=800,
        font = dict(color='#fff', size=12)
    )

    fig.show()

使用方式

运行后你可以:

  • 用顶部下拉菜单切换全选/单项目显示
  • 直接点击图例上的任意项目,即可单独切换该曲线的显示状态,支持同时选中任意多个

方案2:用Dash框架实现下拉多选组件

如果一定要用下拉框选择多个项目的交互形式,可以引入轻量的Dash框架,利用其dcc.Dropdown组件的multi=True参数实现多选,回调函数根据选中的项目列表动态控制曲线可见性即可,核心示例代码如下:

from dash import Dash, dcc, html, Input, Output
import plotly.graph_objects as go

app = Dash(__name__)
# 注意运行前先定义好你的actual/forecast_1/forecast_2数据
cols = actual.columns.tolist()

app.layout = html.Div([
    dcc.Dropdown(
        id='project-select',
        options=[{"label": col, "value": col} for col in cols],
        value=cols, # 默认全选
        multi=True # 开启多选开关
    ),
    dcc.Graph(id='multi-plot')
])

@app.callback(
    Output('multi-plot', 'figure'),
    Input('project-select', 'value')
)
def update_fig(selected_cols):
    fig = go.Figure()
    for col in selected_cols:
        fig.add_trace(go.Scatter(x=actual.index, y=actual[col], name=f"{col} - 真实值"))
        fig.add_trace(go.Scatter(x=forecast_1.index, y=forecast_1[col], name=f"{col} - SI预测"))
        fig.add_trace(go.Scatter(x=forecast_2.index, y=forecast_2[col], name=f"{col} - LSTM预测"))
    # 其他样式配置和你原有代码一致
    fig.update_layout(
        plot_bgcolor = '#010028',
        paper_bgcolor = '#010028',
        height=800,
        font = dict(color='#fff', size=12)
    )
    return fig

if __name__ == '__main__':
    app.run_server(debug=True)

内容的提问来源于stack exchange,提问作者Starry Night

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:48:01