1

Here's my data:

import plotly.graph_objects as go
import pandas as pd 

data = {'vocab':['today', 'started', 'half', 'slowly', "probably", "took", "two", "daily", "change", "life",
                "effect", "wrong", "talk", "hard"], 
        'x':[-12.9, -23.4, -7.1, -6.3, -20.5, -5.8, -32.6, -8.3, -4.2, -12.3, -9.6, -4.2, - 20.4, - 15.7],
        'y':[21.6, 21.8, 33.2, 22.7, 34, 0.4, 22.4, 31.9, 17.9, 20.13, 25.7, 22.3, 26.8, 19.2],
        'freq':[277, 491, 264, 138, 250, 279, 753, 93, 77, 113, 425, 122, 326, 345]} 

df = pd.DataFrame(data)

fig = go.Figure()

config = dict({'scrollZoom': True})

fig.add_trace(go.Scatter(x = df.x, y = df.y, 
                         mode = "markers + text", 
                         text = df['vocab'], 
                         marker = dict(
                         size = df['freq'],
                         sizemode = 'area',
                         sizeref=2.*max(df['freq'])/(295.**2))))


fig.update_layout(title = "help",
                 hovermode='closest',
                 yaxis=dict(zeroline=False, showgrid=False),
                 xaxis=dict(zeroline=False, showgrid=False),
                 showlegend = False,
                 width = 1000,
                 height = 800,
                 template = "presentation")

fig.show(config=config)

Is there a way to build a custom slider that, as you slide it, filters the bubbles based on the "freq" variable?

I'm assuming it would work best by percentile, but just for simplicity, let's say the slider was set at the value 100, that would filter out all "freq" less than 100, only showing the bubbles with a "freq" greater than 100. I haven't seen Plotly sliders used this way, so I'm not sure how to build this.

Christian
  • 139
  • 9
  • It seems to me that the easier way to achieve it is via dash. Otherwise you need to generate all possible plots and play with the `visible` parameter. – rpanai Jul 13 '20 at 14:59

1 Answers1

2

If you look for a dash solution it's not too complicated to add a slider and a filter within the callback as following

# app.py
import pandas as pd
import plotly.graph_objs as go
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html

# Data
data = {'vocab':['today', 'started', 'half', 'slowly', "probably", "took", "two", "daily", "change", "life",
                "effect", "wrong", "talk", "hard"], 
        'x':[-12.9, -23.4, -7.1, -6.3, -20.5, -5.8, -32.6, -8.3, -4.2, -12.3, -9.6, -4.2, - 20.4, - 15.7],
        'y':[21.6, 21.8, 33.2, 22.7, 34, 0.4, 22.4, 31.9, 17.9, 20.13, 25.7, 22.3, 26.8, 19.2],
        'freq':[277, 491, 264, 138, 250, 279, 753, 93, 77, 113, 425, 122, 326, 345]} 

df = pd.DataFrame(data)

app = dash.Dash()
app.layout = html.Div([
       dcc.Slider(
        id='my-slider',
        min=50,
        max=1000,
        step=50,
        value=50,
        marks={i: i for i in range(50,1050, 50)}
    ),

    html.Hr(),
    dcc.Graph(id='display-selected-values',
              config={'scrollZoom': True}),

])

@app.callback(
    dash.dependencies.Output('display-selected-values', 'figure'),
    [dash.dependencies.Input('my-slider', 'value')])
def update_output(value):
    ddf = df[df["freq"]>value]
    fig = go.Figure()

    config = dict({'scrollZoom': True})

    fig.add_trace(go.Scatter(x = ddf["x"],
                             y = ddf["y"], 
                             mode = "markers + text", 
                             text = ddf['vocab'], 
                             marker = dict(
                             size = ddf['freq'],
                             sizemode = 'area',
                             sizeref=2.*max(ddf['freq'])/(295.**2))))


    fig.update_layout(title = "help",
                     hovermode='closest',
                     yaxis=dict(zeroline=False, showgrid=False),
                     xaxis=dict(zeroline=False, showgrid=False),
                     showlegend = False,
                     width = 1000,
                     height = 800,
                     template = "presentation")
    return fig
    
if __name__ == '__main__':
    app.run_server()

If you want a plotly only solution you should create a plot for every parameter in your slider and play with the visible option. See doc

rpanai
  • 12,515
  • 2
  • 42
  • 64
  • @Christian in general whenever I need to use a simple slider or dropdown I prefer to use plotly only but in this case, despite it will be possible to achieve, is going to be a little complicated. [Here](https://stackoverflow.com/a/61754644/4819376) there is an example of the same results using plotly or dash. – rpanai Jul 13 '20 at 15:45
  • My backup plan was to do a dropdown that displayed the options with varying frequencies but I was hoping to find a more sophisticated solution (and I did!). – Christian Jul 13 '20 at 16:24