2

I am trying to create an interactive boxplot with ipywidgets and Plotly.

I started by looking at this example

While this is fine, I'd like to change the groupings of the boxplot based on a dropdown input.

With interact I can do this:

import datetime
import numpy as np
import pandas as pd

import plotly.graph_objects as go
from ipywidgets import widgets

df = pd.read_csv(
 'https://raw.githubusercontent.com/yankev/testing/master/datasets/nycflights.csv')
df = df.drop(df.columns[[0]], axis=1)

from ipywidgets import interact

def view_image(col):
    fig = go.FigureWidget()
    for val in df[col].unique():
        groupData = df.query(f'{col} == "{val}"')
        fig.add_trace(
            go.Box(y = groupData['distance'],
                  name = val)
        )
    fig.show()
    

    
interact(view_image, col = ['origin', 'carrier'])

And the result is that I can change the column based on which the data is grouped.

However, I would like to have more control on the widgets, like in the official example.

This is what I am trying (and failing):

# Assign an empty figure widget with two traces
gdata = []
for origin in df.origin.unique():
    groupData = df.query(f'origin == "{origin}"')
    gdata.append(
        go.Box(y = groupData['distance'],
              name = origin)
    )
g = go.FigureWidget(data=gdata,
                    layout=go.Layout(
                        title=dict(
                            text='NYC FlightDatabase'
                        ),
                        barmode='overlay'
                    ))

def response_box(change):
    col = column.value
    with g.batch_update():
        gdata = []
        for val in df[col].unique():
            groupData = df.query(f'{col} == "{val}"')
            gdata.append(
                go.Box(y = groupData['distance'],
                      name = val)
            )
        g.data = gdata

column = widgets.Dropdown(
    options=['origin','carrier']
)
column.observe(response_box, 'value')
container2 = widgets.HBox([column])
widgets.VBox([container2,
              g])

Note that since I have new groupings, I cannot just go into g.data[index].y and change per index, but I have to re-generate the figure as in the interact function.

This particular iteration gives me a "you cannot update data directly" error. I tried in a few different ways, but I don't seem to find one that works.

Any idea?

1 Answer 1

1
  • it's not clear how you want to interact with the dimensions of data. So I've gone with defining x and color of figure, plus filtering by origin, dest, carrier
  • box plots are far simpler to create using Plotly Express so have used that
  • it then really simplifies to passing parameters. Have used https://ipywidgets.readthedocs.io/en/latest/examples/Using%20Interact.html with decorator
import datetime
import numpy as np
import pandas as pd

import plotly.graph_objects as go
import plotly.express as px
from ipywidgets import widgets
from ipywidgets import interact

df = pd.read_csv(
    "https://raw.githubusercontent.com/yankev/testing/master/datasets/nycflights.csv"
)
df = df.drop(df.columns[[0]], axis=1)

@interact
def view_image(
    col=widgets.Dropdown(
        description="Plot:", value="carrier", options=["origin", "carrier"]
    ),
    filtercol=widgets.Dropdown(
        description="Filter by:", value="carrier", options=["origin", "dest", "carrier"]
    ),

    filter=widgets.Text(
        description="Filter:", value=""
    ),
):
    # check if filter results in any rows... if not all data...
    if df[filtercol].eq(filter).any():
        dfp = df.loc[df[filtercol].eq(filter)]
    else:
        dfp = df
    fig = px.box(dfp, x=col, y="distance", color=col)
    go.FigureWidget(fig.to_dict()).show()

enter image description here

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

1 Comment

Yeah, Interact works pretty well, but it doesn't really give me control on the widgets layout. However, looking at the link to their documentation, I found interactive_output which should give me more control on how the widgets are arranged.

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.