Rony Armon
Rony Armon

Reputation: 338

Selecting dataframe rows for a scatter plot in bokeh

What is the best way to select specific rows from a dataframe using a dropdown meun in Bokeh? I've tried using the modified script below that charts iris but got only a blank screen the server:

import pandas as pd

from bokeh.models import ColumnDataSource, ColorBar, CategoricalColorMapper
from bokeh.plotting import figure, show
from bokeh.palettes import Spectral6
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.layouts import widgetbox

from bokeh.sampledata.iris import flowers as df
source = ColumnDataSource(df)

mapper = CategoricalColorMapper(
    factors=['setosa', 'virginica', 'versicolor'], 
    palette=['red', 'green', 'blue']) 

plot = figure(x_axis_label='petal_length', y_axis_label='sepal_length',plot_width=400,plot_height=400)
plot.circle('petal_length', 'sepal_length',size=4, source=source, 
            color={'field': 'species', 
                   'transform': mapper}) 

species=list (df['species'].unique())

menu = Select(options=species,value='setosa', title='Species')

# Add callback to widgets
def callback(attr, old,new):
    source_data=pd.DataFrame(source.data)
    new_data= source_data.loc[source_data['species']==menu.value]
    new_data_dict=dict (new_data)
    source.data=new_data_dict

menu.on_change('value', callback)

layout = column(menu, plot)
curdoc().add_root(layout)

The first part is a given example so the the chart without the menu works fine. My issue is with the design of the callback function to select specific rows from the dataframe.

Upvotes: 1

Views: 1034

Answers (2)

Torus
Torus

Reputation: 188

  1. You forgot to import Select. Add from bokeh.models.widgets import Select.
  2. Note how you override the data source in the callback, so after one selection all species data but one will be gone. So you will need to change your logic of how you switch the data.

Upvotes: 0

dernk
dernk

Reputation: 146

It looks like you forgot to specify the row input for .loc which I assume you want all rows where the species column equals menu.value. Try this in place of your new_data assignment

new_data = source_data.loc[:,source_data['species']==menu.value]

Alternatively without .loc you could use boolean masking

new_data = source_data[source_data['species'] == menu.value]

Upvotes: 1

Related Questions