0

I want to change the dropdown button with an input box so I can search for the item by starting to type the name and then select. So far I have a drop down box where you can select either one item or all of them at the same time. However, I want the user to be able to start typing the name of the item and then click and select the item they want to display their graph.

As I am new to plotly, any suggestion is very welcome and appreciated :)

Here is what the plot looks like so far:

enter image description here

My code:

def interactive_multi_plot(actual, forecast_1, forecast_2, title, addAll = True):
fig = go.Figure()
    

for column in forecast_1.columns.to_list():
    fig.add_trace(
        go.Scatter(
            x = forecast_1.index,
            y = forecast_1[column],
            name = "Forecast_SI"
        )

    )

    
    button_all = dict(label = 'All',
                  method = 'update',
                  args = [{'visible': forecast_1.columns.isin(forecast_1.columns),
                           'title': 'All',
                           'showlegend':True}])
    
for column in forecast_2.columns.to_list():
    fig.add_trace(
        go.Scatter(
            x = forecast_2.index,
            y = forecast_2[column],
            name = "Forecast_LSTM" 
        )

    )

    
    button_all = dict(label = 'All',
                  method = 'update',
                  args = [{'visible': forecast_2.columns.isin(forecast_2.columns),
                           'title': 'All',
                           'showlegend':True}])
for column in actual.columns.to_list():
    fig.add_trace(
        go.Scatter(
            x = actual.index,
            y = actual[column],
            name = "True values" 
        )

    )

    
    button_all = dict(label = 'All',
                  method = 'update',
                  args = [{'visible': actual.columns.isin(actual.columns),
                           'title': 'All',
                           'showlegend':True}])
    
fig.layout.plot_bgcolor = '#010028'
fig.layout.paper_bgcolor = '#010028'
def create_layout_button(column):
    return dict(label = column,
                method = 'update',
                args = [{'visible': actual.columns.isin([column]),
                         'title': column,
                         'showlegend': True}])
fig.update_layout(
    updatemenus=[go.layout.Updatemenu(
        active = 0,
        buttons = ([button_all] * addAll) +  list(actual.columns.map(lambda column: create_layout_button(column)))
        )
    ]     
)
# Update remaining layout properties
fig.update_layout(
    title_text=title,
    height=800,
    font = dict(color='#fff', size=12)
)


fig.show()

This is the error I receive:

enter image description here

Starry Night
  • 131
  • 2
  • 11

1 Answers1

1
  • small changes to interactive_multi_plot().
    1. for all three add_trace() add meta = column for each of the scatter creations
    2. change to return fig instead of fig.show()
  • simulate some data and call interactive_multi_plot(). I have assumed all three data frames have the same columns
S = 100
C = 10

actual = pd.DataFrame(
    {
        c: np.sort(np.random.uniform(0, 600, S))
        for c in [
            f"{a}{b}-{c}"
            for a, b, c in zip(
                np.random.randint(100, 200, C),
                np.random.choice(list("ABCDEF"), C),
                np.random.randint(300, 400, C),
            )
        ]
    }
)

f1 = actual.assign(**{c:actual[c]*1.1 for c in actual.columns})
f2 = actual.assign(**{c:actual[c]*1.2 for c in actual.columns})

fig = interactive_multi_plot(actual, f1, f2, "Orders")

solution

  • use dash this does support interactive drop downs
  • simple case of show figure and define a callback on item selected from dash drop down
  • it could be considered that updatemenus is now redundant. I have not considered sync of updatemenus back to dash drop down
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash

# Build App
app = JupyterDash(__name__)
app.layout = html.Div(
    [
        dcc.Dropdown(
            id="lines",
            options=[{"label": c, "value": c} for c in ["All"] + actual.columns.tolist()],
            value="All",
        ),
        dcc.Graph(id="interactive-multiplot", figure=fig),
    ]
)

@app.callback(
    Output("interactive-multiplot", "figure"),
    Input("lines", "value"),
    State("interactive-multiplot", "figure"),
)
def updateGraphCB(line, fig):
    # filter traces...
    fig = go.Figure(fig).update_traces(visible=False).update_traces(visible=True, selector={"meta":line} if line!="All" else {})
    # syn button to dash drop down
    fig = fig.update_layout(updatemenus=[{"active":0 if line=="All" else actual.columns.get_loc(line)+1}])
    return fig

app.run_server(mode="inline")

enter image description here

Rob Raymond
  • 29,118
  • 3
  • 14
  • 30
  • Hello Rob! Thank you very much for your help! I receive an error when i run the code: the server does not accept the connection – Starry Night Aug 25 '21 at 07:35
  • hi - which line? what runtime environment are you using? (jupyter?) – Rob Raymond Aug 25 '21 at 07:50
  • Yes Im using jupyter notebook. I added the error above. – Starry Night Aug 25 '21 at 07:51
  • ok - I don't suggest adding an image of an error in an answer. the error is exactly what it says, port 8050 is already being used. in jupyter kernels - restart all kernels... I'm assuming there is already ani python env on your machine using port 8050 – Rob Raymond Aug 25 '21 at 07:59
  • Yes, you are right about the error in the answer. I apologise. I restarted all kernels. Still same error. :( – Starry Night Aug 25 '21 at 08:15
  • for reference: https://github.com/plotly/jupyter-dash/issues/33. try running on a different port, really depends on what else you run on your computer... change final line `app.run_server(mode="inline", port=8051)` and select a port that is not in use on your computer – Rob Raymond Aug 25 '21 at 14:01
  • Hello Rob! Thank you for your answers! Unfortunately, I am using AWS and apparently it does not support Dash. This is why I keep having this port connection issue. Is there any other package I could use to achieve same result? – Starry Night Sep 21 '21 at 08:31
  • I've not done it, you can run dash server less https://stackoverflow.com/questions/66845303/deploying-a-plotly-dash-app-to-aws-using-serverless-framework – Rob Raymond Sep 21 '21 at 10:24