Adding matplotlib into dash, and assigning x,y properly?

Hello everyone,

I am new to dash.
I have a test dataframe consisting of 5 columns. I used the sample codes Add/remove graph, and Create interactive matplotlib with dash to add the matplotlib plots to Iframe. In my code, there are add chart and remove buttons. I also have a dropdown menu for each adding plot.
I don’t understand why assigning x, y in ax.plot(selected_col, ‘col5’) does not properly work. Also, I am getting this warning: “Starting a Matplotlib GUI outside of the main thread will likely fail.”
I will appreciate any helps.

from dash import Dash, html, dcc, Output, Input, State, MATCH, ALL
import plotly.express as px
import pandas as pd
import numpy as np
import dash_bootstrap_components as dbc
import matplotlib.pyplot as plt
import mpld3

df = pd.read_csv('test.csv')

app = Dash(__name__, external_stylesheets=[dbc.themes.SUPERHERO])

app.layout = html.Div([
    html.Div(children=[
        html.Button('add Chart', id='add-chart', n_clicks=0)
    ]),
    html.Div(id='container', children=[])
])


@app.callback(
    Output('container', 'children'),
    [Input('add-chart', 'n_clicks'),
    Input({'type': 'remove-btn', 'index': ALL}, 'n_clicks')],
    [State('container', 'children')],
    prevent_initial_call=True
)
def display_graphs(n_clicks, n, div_children):

    ctx = dash.callback_context
    triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
    elm_in_div = len(div_children)

    if triggered_id == 'add-chart':
        new_child = html.Div(
            id={'type': 'div-num', 'index': elm_in_div},
            style={'width': '25%',
                   'display': 'inline-block',
                   'outline': 'none',
                   'padding': 5},
            children=[
                dcc.Dropdown(id={'type': 'feature-choice',
                                 'index': n_clicks},
                             options=df.columns.values[0:4],
                             multi=True,
                             clearable=True,
                             value=[]
                ),
                html.Iframe(id={'type': 'line-plot', 'index': n_clicks},
                            srcDoc=None,
                            style={'background-color': 'red', 'margin': '0', 'border-width': '0', 'width': '100%', 'height': '600px'}
                ),
                html.Button("Remove", id={'type': 'remove-btn', 'index': elm_in_div})
            ]
        )
        div_children.append(new_child)
        return div_children

    if triggered_id != 'add-chart':
        for idx, val in enumerate(n):
            if val is not None:
                del div_children[idx]
                return div_children


@app.callback(
    Output({'type': 'line-plot', 'index': MATCH}, 'srcDoc'),
    [Input({'type': 'feature-choice', 'index': MATCH}, 'value')]
)
def update_graph(selected_col):
    if selected_col is None:
        raise PreventUpdate
    fig, ax = plt.subplots(figsize=(3.5, 5.5))
    ax.plot(selected_col, 'col5')
    fig.tight_layout()

    html_matplotlib = mpld3.fig_to_html(fig)
    return html_matplotlib


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

Hi,

out of curiosity: Why do you want to use matplotlib?

I guess the problem lies here:

selected_col is just a string, explicitly one of the column names:

I forgot almost all I knew about matplotlib, but I guess this could work:

ax.plot(df[selected_col],df['col5'])

Thank you for the reply. I tried your suggestion. it raise these errors:
“pandas.errors.InvalidIndexError: (slice(None, None, None), None)”

“Callback error updating {“index”:[“MATCH”],“type”:“line-plot”}.srcDoc”

The reason behind choosing matplotlib is that I think it has more flexibility over the plotting options, however, I am not quite sure about that. I want to have multiple x-axis. so when I choose two or three parameters from the dropdown menu, I see two or three axes

or I want to highlight a section of my plot based on the categories of another column such as below:


I am new to dash. I will appreciate if you have any suggestions on that.

I think I found the issue. The x and y should be in numpy array and not dataframe in order to plot using matplotlib.