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

Dash多数据源Plotly图表仅最后一个正常,如何实现全部图表正常渲染?

问题:多数据源仪表盘仅最后一个图表正常渲染

我正在开发一款仪表盘,允许技术型终端用户添加数据源(以下用CSV文件模拟),目标是每个数据源对应生成一个图表,即3个数据源对应3个图表,以此类推。但当前代码仅对最后一个数据源生效,前2个数据源的图表为空白,仅第三个(实际为第二个,索引从0开始)按预期显示。

以下是简化后的实现代码:

import pandas as pd
from dash import Dash, dcc, html, callback, Output, Input, State
from datetime import date, datetime, timedelta
from io import StringIO
import csv
pd.options.plotting.backend = "plotly"


df0_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
1,3,4,2,5,6,5,2,1,3,4,6
2,4,5,3,6,7,6,3,2,4,5,7
3,5,6,4,7,8,7,4,3,5,6,8
4,6,7,5,8,9,8,5,4,6,7,9
5,7,8,6,9,10,9,6,5,7,8,10
6,8,9,7,10,11,10,7,6,8,9,11
7,9,10,8,11,12,11,8,7,9,10,12
8,10,11,9,12,13,12,9,8,10,11,13
9,11,12,10,13,14,13,10,9,11,12,14
10,12,13,11,14,15,14,11,10,12,13,15
11,13,14,12,15,16,15,12,11,13,14,16
12,14,15,13,16,17,16,13,12,14,15,17
13,15,16,14,17,18,17,14,13,15,16,18
14,16,17,15,18,19,18,15,14,16,17,19
15,17,18,16,19,20,19,16,15,17,18,20
16,18,19,17,20,21,20,17,16,18,19,21
17,19,20,18,21,22,21,18,17,19,20,22'''

df1_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
10,13,14,13,10,9,11,12,14,1,3,4
13,14,12,15,16,15,12,11,13,2,4,5
14,15,13,16,17,16,13,12,14,3,5,6
15,16,14,17,18,17,14,13,15,4,6,7
16,17,15,18,19,18,15,14,16,5,7,8
17,18,16,19,20,19,16,15,17,6,8,9
18,19,17,20,21,20,17,16,18,7,9,10
19,20,18,21,22,21,18,17,19,8,10,11
13,9,11,2,5,6,5,2,1,3,4,6
14,16,12,3,6,7,6,3,2,4,5,7
15,17,13,4,7,8,7,4,3,5,6,8
16,18,14,5,8,9,8,5,4,6,7,9
17,19,15,6,9,10,9,6,5,7,8,10
18,20,16,7,10,11,10,7,6,8,9,11
19,21,17,8,11,12,11,8,7,9,10,12
20,22,,9,12,13,12,9,8,10,11,13'''

df_list = []
dfstr_list = [df0_str, df1_str]
for df_str in dfstr_list:
    csvStringIO = StringIO(df_str)
    df_list.append(pd.read_csv(csvStringIO, sep=","))
my_children = []
for num, df in enumerate(df_list):
    my_children.append(html.H3(
        children=f"name of {num}",
    ))
    my_children.append(dcc.Store(id=f'data_{num}', data=df.to_dict()))
    my_children.append(dcc.Input(id=f'range_{num}', type='number', value=12, min=1, step=1))
    my_children.append(html.Div(dcc.Graph(id=f'fig_{num}', )))

# for child in my_children:
#     print(child)

@callback(
    Output(f'fig_{num}', 'figure'),
    Input(f'range_{num}', 'value'),
    State(f'data_{num}', 'data')
)
def update_graph(range_selected, data):
    df_for_figure = pd.DataFrame.from_dict(data).iloc[-range_selected:, :]
    fig = df_for_figure.plot()
    return fig

app = Dash(__name__)


app.layout = html.Div(
    children=my_children
)



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

问题原因

你当前只定义了一个回调函数,而这个回调里的num变量是循环结束后的最终值(这里是1,因为df_list有2个元素,循环时num从0到1,循环结束后保留1)。也就是说,这个回调只绑定了fig_1这个图表组件,而fig_0没有对应的回调函数来更新它,所以前一个图表始终是空白。

解决方案

需要为每个数据源动态生成对应的回调函数,可以在循环遍历数据源的时候,为每个num创建独立的回调。修改后的代码如下:

import pandas as pd
from dash import Dash, dcc, html, callback, Output, Input, State
from datetime import date, datetime, timedelta
from io import StringIO
import csv
pd.options.plotting.backend = "plotly"


df0_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
1,3,4,2,5,6,5,2,1,3,4,6
2,4,5,3,6,7,6,3,2,4,5,7
3,5,6,4,7,8,7,4,3,5,6,8
4,6,7,5,8,9,8,5,4,6,7,9
5,7,8,6,9,10,9,6,5,7,8,10
6,8,9,7,10,11,10,7,6,8,9,11
7,9,10,8,11,12,11,8,7,9,10,12
8,10,11,9,12,13,12,9,8,1</think_never_used_51bce0c785ca2f68081bfa7d91973934>
<answer>
# 问题:多数据源仪表盘仅最后一个图表正常渲染

我正在开发一款仪表盘,允许技术型终端用户添加数据源(以下用CSV文件模拟),目标是每个数据源对应生成一个图表,即3个数据源对应3个图表,以此类推。但当前代码仅对最后一个数据源生效,前2个数据源的图表为空白,仅第三个(实际为第二个,索引从0开始)按预期显示。

以下是简化后的实现代码:
```python
import pandas as pd
from dash import Dash, dcc, html, callback, Output, Input, State
from datetime import date, datetime, timedelta
from io import StringIO
import csv
pd.options.plotting.backend = "plotly"


df0_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
1,3,4,2,5,6,5,2,1,3,4,6
2,4,5,3,6,7,6,3,2,4,5,7
3,5,6,4,7,8,7,4,3,5,6,8
4,6,7,5,8,9,8,5,4,6,7,9
5,7,8,6,9,10,9,6,5,7,8,10
6,8,9,7,10,11,10,7,6,8,9,11
7,9,10,8,11,12,11,8,7,9,10,12
8,10,11,9,12,13,12,9,8,10,11,13
9,11,12,10,13,14,13,10,9,11,12,14
10,12,13,11,14,15,14,11,10,12,13,15
11,13,14,12,15,16,15,12,11,13,14,16
12,14,15,13,16,17,16,13,12,14,15,17
13,15,16,14,17,18,17,14,13,15,16,18
14,16,17,15,18,19,18,15,14,16,17,19
15,17,18,16,19,20,19,16,15,17,18,20
16,18,19,17,20,21,20,17,16,18,19,21
17,19,20,18,21,22,21,18,17,19,20,22'''

df1_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
10,13,14,13,10,9,11,12,14,1,3,4
13,14,12,15,16,15,12,11,13,2,4,5
14,15,13,16,17,16,13,12,14,3,5,6
15,16,14,17,18,17,14,13,15,4,6,7
16,17,15,18,19,18,15,14,16,5,7,8
17,18,16,19,20,19,16,15,17,6,8,9
18,19,17,20,21,20,17,16,18,7,9,10
19,20,18,21,22,21,18,17,19,8,10,11
13,9,11,2,5,6,5,2,1,3,4,6
14,16,12,3,6,7,6,3,2,4,5,7
15,17,13,4,7,8,7,4,3,5,6,8
16,18,14,5,8,9,8,5,4,6,7,9
17,19,15,6,9,10,9,6,5,7,8,10
18,20,16,7,10,11,10,7,6,8,9,11
19,21,17,8,11,12,11,8,7,9,10,12
20,22,,9,12,13,12,9,8,10,11,13'''

df_list = []
dfstr_list = [df0_str, df1_str]
for df_str in dfstr_list:
    csvStringIO = StringIO(df_str)
    df_list.append(pd.read_csv(csvStringIO, sep=","))
my_children = []
for num, df in enumerate(df_list):
    my_children.append(html.H3(
        children=f"name of {num}",
    ))
    my_children.append(dcc.Store(id=f'data_{num}', data=df.to_dict()))
    my_children.append(dcc.Input(id=f'range_{num}', type='number', value=12, min=1, step=1))
    my_children.append(html.Div(dcc.Graph(id=f'fig_{num}', )))

# for child in my_children:
#     print(child)

@callback(
    Output(f'fig_{num}', 'figure'),
    Input(f'range_{num}', 'value'),
    State(f'data_{num}', 'data')
)
def update_graph(range_selected, data):
    df_for_figure = pd.DataFrame.from_dict(data).iloc[-range_selected:, :]
    fig = df_for_figure.plot()
    return fig

app = Dash(__name__)


app.layout = html.Div(
    children=my_children
)



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

问题原因

你当前只定义了一个回调函数,而这个回调里的num变量是循环结束后的最终值(这里是1,因为df_list有2个元素,循环时num从0到1,循环结束后保留1)。也就是说,这个回调只绑定了fig_1这个图表组件,而fig_0没有对应的回调函数来更新它,所以前一个图表始终是空白。

解决方案

需要为每个数据源动态生成对应的回调函数,可以在循环遍历数据源的时候,为每个num创建独立的回调。修改后的代码如下:

import pandas as pd
from dash import Dash, dcc, html, callback, Output, Input, State
from datetime import date, datetime, timedelta
from io import StringIO
import csv
pd.options.plotting.backend = "plotly"


df0_str = '''"January","February","March","April","May","June","July","August","September","October","November","December"
1,3,4,2,5,6,5,2,1,3,4,6
2,4,5,3,6,7,6,3,2,4,5,7
3,5,6,4,7,8,7,4,3,5,6,8
4,6,7,5,8,9,8,5,4,6,7,9
5,7,8,6,9,10,9,6,5,7,8,10
6,8,9,7,10,11,10,7,6,8,9,11
7,9,10,8,11,12,11,8,7,9,10,12
8,10,11,9,12,13,12,9,8,10,11,13
9,11,12,10,13,14,13,10,9,11,12,14
10,12,13,11,14,15,14,11,10,12,13,15
11,1
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 10:35:12