我用Python创建了一个非常简单的Dash plot代码。
- 用户拖拽输入文件(任何带有字符串列名的excel文件都可以)
- 从x轴和y轴的下拉列表中选择所需的列名。
- 显示一个简单的图形
然而,在用户拖动输入文件之前,我一直有这些错误,直到用户上传任何内容,代码看到& None"
我能做些什么让它闭嘴吗?
代码如下:
import base64
import datetime
import io
import plotly.graph_objs as go
import cufflinks as cf
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_table
import pandas as pd
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
server = app.server
colors = {"graphBackground": "#F5F5F5", "background": "#ffffff", "text": "#000000"}
app.layout = html.Div(
[
dcc.Upload(
id="upload-data",
children=html.Div(["Drag and Drop or ", html.A("Select Files")]),
style={
"width": "100%",
"height": "60px",
"lineHeight": "60px",
"borderWidth": "1px",
"borderStyle": "dashed",
"borderRadius": "5px",
"textAlign": "center",
"margin": "10px",
},
# Allow multiple files to be uploaded
multiple=True,
),
dcc.Dropdown(
id='x_dropdown',
options = [],
placeholder="X Axis - Please Select Column"),
dcc.Dropdown(
id='y_dropdown',
options = [],
placeholder="Y Axis - Please Select Column"),
dcc.Graph(id="Mygraph"),
html.Div(id="output-data-upload"),
]
)
@app.callback(Output('Mygraph', 'figure'), [
Input('upload-data', 'contents'),
Input('upload-data', 'filename'),
Input('x_dropdown','value'),
Input('y_dropdown','value')
])
def update_graph(contents, filename, x_dropdown, y_dropdown):
x = []
y = []
if contents:
contents = contents[0]
filename = filename[0]
x_dropdown = str(x_dropdown)
y_dropdown = str(y_dropdown)
df = parse_data(contents, filename)
df = df.set_index(df.columns[0])
x=df[x_dropdown]
y=df[y_dropdown]
fig = go.Figure(
data=[
go.Bar(
x=x,
y=y)
],
layout=go.Layout(
plot_bgcolor=colors["graphBackground"],
paper_bgcolor=colors["graphBackground"]
))
return fig
def parse_data(contents, filename):
content_type, content_string = contents.split(",")
decoded = base64.b64decode(content_string)
try:
if "csv" in filename:
# Assume that the user uploaded a CSV or TXT file
df = pd.read_csv(io.StringIO(decoded.decode("utf-8")))
elif "xls" in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
elif "txt" or "tsv" in filename:
# Assume that the user upl, delimiter = r's+'oaded an excel file
df = pd.read_csv(io.StringIO(decoded.decode("utf-8")), delimiter=r"s+")
except Exception as e:
print(e)
return html.Div(["There was an error processing this file."])
return df
@app.callback(
Output("output-data-upload", "children"),
[Input("upload-data", "contents"),
Input("upload-data", "filename")],
)
def update_table(contents, filename):
table = html.Div()
if contents:
contents = contents[0]
filename = filename[0]
df = parse_data(contents, filename)
table = html.Div(
[
html.Hr(),
html.H5(filename),
html.Hr(),
dash_table.DataTable(
data=df.to_dict("rows"),
columns=[{"name": str(i), "id": str(i)} for i in df.columns],
),
html.Hr(),
html.Div(""),
]
)
return table
# update x_dropdown
@app.callback(Output('x_dropdown', 'options'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_x_dropdown(contents, filename):
contents = contents[0]
filename = filename[0]
if contents is not None:
df = parse_data(contents, filename)
columns = df.columns.values.tolist()
if df is not None:
return [ {'label': x, 'value': x} for x in columns ]
else:
return []
else:
return []
# update y_dropdown
@app.callback(Output('y_dropdown', 'options'),
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_y_dropdown(contents, filename):
contents = contents[0]
filename = filename[0]
if contents is not None:
df = parse_data(contents, filename)
columns = df.columns.values.tolist()
if df is not None:
return [ {'label': x, 'value': x} for x in columns ]
else:
return []
else:
return []
if __name__ == "__main__":
app.run_server(debug=True)
提前感谢!
你的想法是对的:
def update_y_dropdown(contents, filename):
contents = contents[0]
filename = filename[0]
if contents is not None:
# do stuff
让每个回调在尝试做任何事情之前检查实际值。
首先,您应该检查开头的contents是否为none。
第二,重复代码是不好的做法。update_x_dropdown和update_y_dropdown是相同的方法===>只保留一个
@app.callback(
[Output('x_dropdown', 'options'),
Output('y_dropdown', 'options')],
[Input('upload-data', 'contents'),
Input('upload-data', 'filename')])
def update_dropdown(contents, filename):
if not contents or not filename:
return [], []
contents = contents[0]
filename = filename[0]
df = parse_data(contents, filename)
columns = df.columns.values.tolist()
if df is not None:
out = [{'label': x, 'value': x} for x in columns]
return out, out
else:
return [], []