Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Help merging callback with uploaded data

I got a little app running with dash:

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

df = pd.read_csv(r'C:\Users\myfile.csv')

text = 'Col1'
vals = df.groupby([text]).size()
available_indicators = ['Col1', 'Col2', 'Col3', 'Col4', 'Col5', 'Col6', 'Col7']
status_vals = df['Status'].unique()

app.layout = html.Div([
    html.Div([
        html.H1("Welcome to my Dashboard"),
        html.P("Subheader here")
             ], ),
    dcc.Graph(id='donut-with-slider'),
    dcc.Dropdown(
        id='Category',
        options=[{'label': i, 'value': i} for i in available_indicators],
        value='Receiving GBU/GF'),
    dcc.Dropdown(
        id='Status',
        options=[{'label': i, 'value': i} for i in status_vals],
        value='Filled'),
    dcc.Slider(
        id='year-slider',
        min=df['Year'].min(),
        max=df['Year'].max(),
        value=df['Year'].max(),
        marks={str(Year): str(Year) for Year in df['Year'].unique()},
        step=None
            ),
        ])

@app.callback(
    Output('donut-with-slider', 'figure'),
    Input('year-slider', 'value'),
    Input('Category', 'value'),
    Input('Status', 'value'))
def update_figure(selected_year, Category, Status):
    df2 = df[df.Year == selected_year]
    df3 = df2[df2.Status == Status]
    text = Category
    vals = df3.groupby([text]).size()
    fig = go.Figure(data=[go.Pie(labels=vals.index.values, values=vals, hole=0.3)])

    fig.update_layout(transition_duration=500)
    return fig

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

This seems to run correctly and do what I want. But the problem I’m having, after reading through docs for days, is integrating a dcc.Upload such that it actually can output data into the graph. I think I’m somehow both over thinking and under thinking. This is the closest to something that seems to do what I want:


currentdata = pd.read_csv('Most_Recent_Version.csv')

#vals = df.groupby(['Receiving GBU/GF']).size()
text = 'Participant\'s GBU/GF'
vals = currentdata.groupby([text]).size()
#fig = go.Figure(data=[go.Pie(labels=vals.index.values, values=vals, hole=0.3)])
available_indicators = ['Receiving GBU/GF', 'Participant\'s GBU/GF', 'Participant Location', 'Receiving Location', 'Participant\'s Country', 'Receiving Country', 'Remote']
status_vals = currentdata['Status'].unique()



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
    ),
    html.Div(id='output-data-upload'),
    html.Div([
    html.H1("Welcome to the Preceptorship Dashboard"),
    html.P("Learning Dash is so interesting!!")
         ], ),
    dcc.Graph(id='donut-with-slider'),
    dcc.Dropdown(
        id='Status',
        options=[{'label': i, 'value': i} for i in status_vals],
        value='Filled'),
    dcc.Slider(
        id='year-slider',
        min=df['Year'].min(),
        max=df['Year'].max(),
        value=df['Year'].max(),
        marks={str(Year): str(Year) for Year in df['Year'].unique()},
        step=None
            ),
        ])

def parse_contents(contents, filename, date):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'xls' in filename:
            # Assume that the user uploaded an excel file
            current_date = datetime.date.today() 
    
            current_year = current_date.year 
            
            year_range = current_year - 2018 + 0 
            
            tabs = [] 
            
            for i in range(year_range): 
                text = ' - Assignments' 
                tab_name = str(2018+i)+text 
                tabs.append(tab_name) 
            
            df = pd.read_excel(io.BytesIO(decoded), sheet_name=tabs, header=1, usecols='B:AC') 
            df2 = pd.concat(df, names=['keys'], sort=False) 
            cleaned = df2.reset_index() 
            #keep all the lines that are cleaning up this dataframe, 'cleaned'
            return cleaned
    except Exception as e:
        print(e)
        return html.Div([
            'There was an error processing this file.'
        ])

#I'm hoping it's a simple addition to the callback to get the dataframe from parse_contents()

@app.callback(
    Output('donut-with-slider', 'figure'),
    Input('year-slider', 'value'),
    Input('Category', 'value'),
    Input('Status', 'value'))
def update_figure(selected_year, Category, Status):
  
    df2 = currentdata[currentdata.Year == selected_year]
    df3 = df2[df2.Status == Status]
    text = Category
    vals = df3.groupby([text]).size()
    fig = go.Figure(data=[go.Pie(labels=vals.index.values, values=vals, hole=0.3)])

    fig.update_layout(transition_duration=500)
    return fig


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

I’ve tried doing something like the first example with the table from here but I don’t know how to then have the callback for interactivity.