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

1 Answer 1

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

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

8 Comments

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
hi - which line? what runtime environment are you using? (jupyter?)
Yes Im using jupyter notebook. I added the error above.
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
Yes, you are right about the error in the answer. I apologise. I restarted all kernels. Still same error. :(
|

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.