1

I use the following code dor dcc upload component. I twisted the code that I have seen in this thread. In that thread, plot was rendered using plotly go, however, I would like to use plotly express instead of plotly go. Since px.line expects teh name of dataframe, I write it as px.line(df,...). But, in that thread, df is not defined in the if contents condition(in the answer of that thread.). As I write the df out of that condition, I encounter with the following error UnboundLocalError: local variable 'df' referenced before assignment. The code works when I upload a file. But, I would like to get rid of that error, because it i annoying to see it there. How can I handle this issue?

import base64
import datetime
import io
import plotly.graph_objs as go
import cufflinks as cf
import plotly.express as px
from dash import Dash, html, dcc, Input, Output,dash_table
import dash
from dash.dash_table.Format import Group
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.Graph(id="Mygraph"),
        html.Div(id="output-data-upload"),
    ]
)


@app.callback(
    Output("Mygraph", "figure"),
    [Input("upload-data", "contents"), Input("upload-data", "filename")],
)
def update_lineplot(contents, filename):
    x = []
    y = []
    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)
        #df = df.set_index(df.columns[0])
        x=df['TIME']
        y=df['VALUE2']
    #print(df)
    fig = px.line(df, x="TIME", y=["VALUE1", "VALUE2"],
                         facet_col_wrap=2,
                         facet_row_spacing=0.1,
                         facet_col_spacing=0.09)
    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.H5(filename),
                dash_table.DataTable(
                    data=df.to_dict("rows"),
                    columns=[{"name": i, "id": i} for i in df.columns],
                ),
                html.Hr(),
                html.Div("Raw Content"),
                html.Pre(
                    contents[0:200] + "...",
                    style={"whiteSpace": "pre-wrap", "wordBreak": "break-all"},
                ),
            ]
        )

    return table


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

1 Answer 1

2
+50

All you should do is to define an empty dataframe before the If statement, you will get in the beginning an empty graph and then when you upload a file, you will get your graph.

@app.callback(
    Output("Mygraph", "figure"),
    [Input("upload-data", "contents"), Input("upload-data", "filename")],
)
def update_lineplot(contents, filename):
    x = []
    y = []
    df = pd.DataFrame(columns=["TIME","VALUE1", "VALUE2"])
    if contents:
        contents = contents[0]
        filename = filename[0]
        df = parse_data(contents, filename)
        #df = df.set_index(df.columns[0])
        x=df['TIME']
        y=df['VALUE2']
    #print(df)
    fig = px.line(df, x="TIME", y=["VALUE1", "VALUE2"],
                         facet_col_wrap=2,
                         facet_row_spacing=0.1,
                         facet_col_spacing=0.09)
    return fig

Output:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.