这更有可能是第一次使用Dash Board与Plotly一起使用,没有清楚的了解代码是如何工作的,问题来自哪里。如果您给予我一些建议,我将不胜感激。我试图通过使用上传按钮和下拉栏导入两个CSV文件应该显示所有变量名称,一旦我选择多个变量名称从下拉栏,然后他们应该在x-y图绘制。
代码可以导入两个不同的csv文件并在下拉栏中显示变量,但绘图不起作用。我认为代码不能正确地将值传递到plotly函数。你能检查一下代码吗?问题的根源在哪里?谢谢。
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output, State
import base64
import io
import plotly.express as px
import dash_table
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
# Initialize the app
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
# Define the layout
app.layout = html.Div([
html.H1('CSV File Comparison Dashboard'),
html.Div([
html.H2('File A'),
dcc.Upload(
id='upload-data-A',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '50%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
multiple=False
),
html.Div(id='file-name_A'),
dcc.Dropdown(
id='variable-dropdown-A',
options=[],
value=[],
multi=True
),
dcc.Graph(
id='graph-A'
)
], style={'width': '49%', 'display': 'inline-block', 'vertical-align': 'top'}),
html.Div([
html.H2('File B'),
dcc.Upload(
id='upload-data-B',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '50%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
multiple=False
),
html.Div(id='file-name_B'),
dcc.Dropdown(
id='variable-dropdown-B',
options=[],
value=[],
multi=True
),
dcc.Graph(
id='graph-B'
)
], style={'width': '49%', 'display': 'inline-block', 'vertical-align': 'top'})
])
# Define the callback for updating the variable dropdown menus
@app.callback([Output('variable-dropdown-A', 'options'), Output('variable-dropdown-A', 'value')],
[Input('upload-data-A', 'contents')],
prevent_initial_call=True)
def update_dropdowns_A(list_of_contents_A):
# Initialize empty options for each dropdown
options_A = []
# Check if a csv file has been uploaded for file A
if list_of_contents_A:
# Read the csv file
content_type, content_string = list_of_contents_A.split(',')
decoded = base64.b64decode(content_string)
df_A = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
# Add the column names to the options for file A
options_A = [{"label": col, "value": col} for col in df_A.columns]
return options_A, df_A.columns[0]
else:
# Return the options for both dropdowns
return [], None
@app.callback([Output('variable-dropdown-B', 'options'), Output('variable-dropdown-B', 'value')],
[Input('upload-data-B', 'contents')],
prevent_initial_call=True)
def update_dropdowns_B(list_of_contents_B):
# Initialize empty options for each dropdown
options_B = []
# Check if a csv file has been uploaded for file B
if list_of_contents_B:
# Read the csv file
content_type, content_string = list_of_contents_B.split(',')
decoded = base64.b64decode(content_string)
df_B = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
# Add the column names to the options for file A
options_B = [{"label": col, "value": col} for col in df_B.columns]
return options_B, df_B.columns[0]
else:
# Return the options for both dropdowns
return [], None
# Define the callback for updating the graphs
@app.callback([Output('graph-A', 'figure'), Output('graph-B', 'figure')],
[Input('variable-dropdown-A', 'value'), Input('variable-dropdown-B', 'value')],
[State('upload-data-A', 'contents'), State('upload-data-B', 'contents')],
prevent_initial_call=True)
def update_graphs(variables_A, variables_B, contents_A, contents_B):
if not variables_A or not variables_B:
return {}, {}
# # Initialize empty dataframes for each file
df_A = pd.DataFrame()
df_B = pd.DataFrame()
# # Check if a csv file has been uploaded for file A
# if contents_A is not None:
# # Read the csv file
# content_type, content_string = contents_A.split(',')
# decoded = base64.b64decode(content_string)
# df_A = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
# # Check if a csv file has been uploaded for file B
# if contents_B is not None:
# # Read the csv file
# content_type, content_string = contents_B.split(',')
# decoded = base64.b64decode(content_string)
# df_B = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
# Initialize empty figures for each graph
fig_A = go.Figure()
fig_B = go.Figure()
# Check if any variables have been selected for file A
for var in variables_A:
fig_A.add_trace(go.Scatter(
x=df_A['time'],
y=df_A[var],
mode='lines',
name=var
))
fig_A.update_layout(title='Time Series Plot',
xaxis_title='Time',
yaxis_title='Value')
# Check if any variables have been selected for file B
for var in variables_B:
fig_B.add_trace(go.Scatter(
x=df_B['time'],
y=df_B[var],
mode='lines',
name=var
))
fig_B.update_layout(title='Time Series Plot',
xaxis_title='Time',
yaxis_title='Value')
# Return the figures for both graphs
return fig_A, fig_B
# Update file name
@app.callback(Output('file-name_A', 'children'),
[Input('upload-data-A', 'filename')])
def update_file_name(filename):
if filename is not None:
return html.P(f'File loaded: {filename}')
else:
return html.P('No file loaded')
@app.callback(Output('file-name_B', 'children'),
[Input('upload-data-B', 'filename')])
def update_file_name(filename):
if filename is not None:
return html.P(f'File loaded: {filename}')
else:
return html.P('No file loaded')
# Run the app
if __name__ == '__main__':
app.run_server(debug=True, port = 8000)
关于这个问题的解释和进一步的评论,如果我需要使用子图函数扩展图的数量,该怎么做。
1条答案
按热度按时间8wigbo561#
关于你的代码,我们可以讨论很多事情,但我只关注你的问题,我做了这些修改。
你遇到的主要问题是,当你处理csv文件时,Dash不会将数据存储到本地内存。这意味着当您的
update_dropdowns_x
完成时,相应的df_A
和df_B
将被删除。当您的update_graphs
被触发时,没有数据可供它使用。我添加了两个dcc.Store
对象,用于在回调之间持久化csv中的数据。你会注意到我没有传递dataframe,因为html要求数据在text/json中。这就是使用df_A.to_json(orient="records")
作为输出的原因。然后用黑色处理代码以纠正轻微的格式错误。我还将下拉列表设置为自动包含所有频道,但您可以将[0]添加回返回,以获得原始应用程序的状态。这是一个截图。因为你没有张贴一个csv文件的例子,我只是做了一些事情。