Brendan McDonald
Brendan McDonald

Reputation: 413

Is it possible to build a plotly graph which has a dropdown menu that filters a dataframe?

I have a dataframe that looks like this:

date, sub_id, stat_type, value
jan 1, 1233, link_clicks, 12,
feb 1, 1233, link_clicks, 13,
jan 1, 3424, link_clicks, 23,
feb 1, 3424, link_clicks, 34,
..., 
jan 1, 1233, transaction, 45, 
feb 1, 1233, transaction, 50,
..., 
jan 1, 1233, customer_signups, 9, 
feb 1, 1233, customer_signups, 8
...
etc...

I would like to build a plotly graph which contains a dropdown menu that filters the dataframe by stat_type before graphing the values.

EG if you select "link_clicks" from the dropdown menu it would graph the following values:

date, sub_id, stat_type, value
jan 1, 1233, link_clicks, 12,
feb 1, 1233, link_clicks, 13,
jan 1, 3424, link_clicks, 23,
feb 1, 3424, link_clicks, 34,
etc...

Graphing the filter dataframes using plotly, but there is little documentation of using a dropdown menu as a filter on an individual graph.

I know that plotly is extremely flexible and I am wondering if anyone has built an interactive graph which contains a dropdown menu which acts as a filter on the DF.

Upvotes: 3

Views: 379

Answers (1)

vestland
vestland

Reputation: 61074

You're not specifying how you'd like to plot the different groups, but since you've got several values for value for different sub_id on different dates, I'm guessing that one subset you'd like to plot would look like this:

sub_id      1233  3424
date                  
2020-01-01    12    24
2020-02-01    14    20
2020-03-01     4     2

If that's the case, then the answer to your question is yes:

Plot 1: Figure when clicking link_clicks

enter image description here

Plot 2: Figure when clicking transaction

enter image description here

Code:

# Imports
import plotly.graph_objs as go
import pandas as pd
import numpy as np

dfi=pd.DataFrame({'date': {0: '2020.01.01',
  1: '2020.01.01',
  2: '2020.01.01',
  3: '2020.01.01',
  4: '2020.01.01',
  5: '2020.01.01',
  6: '2020.02.01',
  7: '2020.02.01',
  8: '2020.02.01',
  9: '2020.02.01',
  10: '2020.02.01',
  11: '2020.02.01',
  12: '2020.03.01',
  13: '2020.03.01',
  14: '2020.03.01',
  15: '2020.03.01',
  16: '2020.03.01',
  17: '2020.03.01'},
 'sub_id': {0: 1233,
  1: 1233,
  2: 1233,
  3: 3424,
  4: 3424,
  5: 3424,
  6: 1233,
  7: 1233,
  8: 1233,
  9: 3424,
  10: 3424,
  11: 3424,
  12: 1233,
  13: 1233,
  14: 1233,
  15: 3424,
  16: 3424,
  17: 3424},
 'stat_type': {0: 'link_clicks',
  1: 'transaction',
  2: 'customer_signups',
  3: 'link_clicks',
  4: 'transaction',
  5: 'customer_signups',
  6: 'link_clicks',
  7: 'transaction',
  8: 'customer_signups',
  9: 'link_clicks',
  10: 'transaction',
  11: 'customer_signups',
  12: 'link_clicks',
  13: 'transaction',
  14: 'customer_signups',
  15: 'link_clicks',
  16: 'transaction',
  17: 'customer_signups'},
 'value': {0: 12,
  1: 50,
  2: 9,
  3: 24,
  4: 100,
  5: 18,
  6: 14,
  7: 24,
  8: 39,
  9: 20,
  10: 10,
  11: 8,
  12: 4,
  13: 2,
  14: 3,
  15: 2,
  16: 1,
  17: 1}})

# change some types 
dfi['date']=pd.to_datetime(dfi['date'])
dfi['sub_id']=dfi['sub_id'].astype(str)
df=dfi

# split df by stat_type and organize them in a dict
groups = df['stat_type'].unique().tolist()
dfs={}
for g in groups:
    dfs[str(g)]=df[df['stat_type']==g]

# pivot data to get different sub_id across dates
dfp={}
for df in dfs:
    dfp[df]=dfs[df].pivot(index='date', columns='sub_id', values='value')

# one trace for each column per dataframe
fig=go.Figure()

# set up the first trace
fig.add_trace(go.Scatter(x=dfp['link_clicks'].index,
                             y=dfp['link_clicks']['1233'],
                             visible=True)
             )

fig.add_trace(go.Scatter(x=dfp['link_clicks'].index,
                             y=dfp['link_clicks']['3424'],
                             visible=True)
             )

# plotly start
# buttons for menu 1, names
updatemenu=[]
buttons=[]

# button with one option for each dataframe
for df in dfp.keys():
    buttons.append(dict(method='restyle',
                        label=df,
                        visible=True,
                        args=[{'y':[dfp[str(df)]['1233'].values, dfp[str(df)]['3424'].values],
                               'x':[dfp[str(df)].index],
                               'type':'scatter'}],
                        )
                  )

# some adjustments to the updatemenus
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True

# add dropdown menus to the figure
fig.update_layout(showlegend=False, updatemenus=updatemenu)

# add notations to the dropdown menus
fig.update_layout(
    annotations=[
        go.layout.Annotation(text="<b>stat_type:</b>",
                             x=-0.3, xref="paper",
                             y=1.1, yref="paper",
                             align="left", showarrow=False),
                          ]
)

fig.show()

Upvotes: 2

Related Questions