pythonplotly

plotly histogram with filtering toolbar - python


I'm trying to generate a plotly histogram that can be filtered by values with a df column. Below, in dataset, I want to be able to filter the values in item to show the distribution of values for each unique value.

However, all I am able to display is one single value. I can't change values to show the results of differing items.

dataset = pd.DataFrame(
    {'item': ['A', 'A', 'B', 'C', 'D', 'A', 'A', 'B', 'C', 'D', 'A', 'A', 'B', 'C', 'D'],
    'value': [27, 33, 3, 26, 8, 27, 3, 13, 16, 2, 27, 17, 12, 6, 28],
    }
)

continuous_vars = ["item"]

fig = go.Figure()

fig.add_trace(
    go.Histogram(x = dataset.item,
                 xbins=go.histogram.XBins(size=5), # Change the bin size
                 marker=go.histogram.Marker(color="orange"), # Change the color
             )
)

buttons = []

for col in continuous_vars:
    buttons.append(dict(method='restyle',
                        label=col,
                        visible=True,
                        args=[{"x":[dataset[col]],
                               "type":'histogram'}, [0]],
                        )
                  )

updatemenu = []
your_menu = dict()
updatemenu.append(your_menu)

updatemenu[0]['buttons'] = buttons
updatemenu[0]['direction'] = 'down'
updatemenu[0]['showactive'] = True

fig.update_layout(showlegend=False, updatemenus=updatemenu)
fig.show()

Solution

  • The issue with your current approach is that you're creating a histogram of the 'item' column itself, but what you likely want is to show the distribution of 'value' filtered by each 'item'.

    import pandas as pd
    import plotly.graph_objects as go
    
    # Sample dataset
    dataset = pd.DataFrame(
        {'item': ['A', 'A', 'B', 'C', 'D', 'A', 'A', 'B', 'C', 'D', 'A', 'A', 'B', 'C', 'D'],
         'value': [27, 33, 3, 26, 8, 27, 3, 13, 16, 2, 27, 17, 12, 6, 28],
        }
    )
    
    # Create the figure
    fig = go.Figure()
    
    # Add an initial empty histogram
    fig.add_trace(
        go.Histogram(
            x=[],
            marker=dict(color="orange"),
            name="Value Distribution"
        )
    )
    
    # Create buttons to filter by each unique item
    buttons = []
    unique_items = dataset['item'].unique()
    
    # Add a button for "All" items
    buttons.append(
        dict(
            method='update',
            label='All',
            args=[
                {'x': [dataset['value']]},
                {'title': 'Distribution of all values'}
            ]
        )
    )
    
    # Add a button for each unique item
    for item in unique_items:
        filtered_data = dataset[dataset['item'] == item]['value']
        buttons.append(
            dict(
                method='update',
                label=f'Item {item}',
                args=[
                    {'x': [filtered_data]},
                    {'title': f'Distribution of values for Item {item}'}
                ]
            )
        )
    
    # Create the dropdown menu
    updatemenu = [
        dict(
            buttons=buttons,
            direction='down',
            showactive=True,
            x=0.1,
            y=1.15,
            xanchor='left',
            yanchor='top'
        )
    ]
    
    # Set the layout
    fig.update_layout(
        title='Distribution of values',
        xaxis_title='Value',
        yaxis_title='Count',
        updatemenus=updatemenu,
        margin=dict(t=80),
        bargap=0.1
    )
    
    # Set the initial display to show all values
    fig.update_traces(x=dataset['value'])
    
    # Show the figure
    fig.show()
    

    The Graph

    <iframe src="https://bhargav-ravinuthala.github.io/plotyd/" width="700" height="450"></iframe>