Rachel
Rachel

Reputation: 1967

Label and color glyph in bokeh

I am trying out bokeh. It's quite fun so far. But I am not totally getting the hang of it. My goal is to make a simple but interactive scatter chart.

I have three main issues:

  1. I want to label the scatter plot with names
  2. I want the scatter to be colored in accordance to colors
  3. I would love widgets where I can decide if the colors and names are displayed.

Here is what I have done so far. I tried to use LabelSet but I am stuck. Any help is greatly appreciated!

# interactive widget bokeh figure
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
from bokeh.models import Range1d, LabelSet, Label
import numpy as np

# data
x = [-4, 3, 2, 4, 10, 11, -2, 6]
y = [-3, 2, 2, 9, 11, 12, -5, 6]
names = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
colors =['r', 'y', 'y', 'r', 'g', 'g', 'g', 'g']



p = figure(plot_height=400, plot_width=400, title="a little interactive chart",         
                tools="crosshair,pan,reset,save,wheel_zoom",
                x_range=[-10, 10], y_range=[-10, 10])

labels = LabelSet(x='x', y='y', text='names', level='glyph',
         x_offset=5, y_offset=5)

p.add_layout(labels)


p.circle(x, y, fill_color="red", line_color="red", size=6)

# Set up widgets
text = TextInput(title="title", value='a little interavtive chart')

# Set up callbacks
def update_title(attrname, old, new):
    p.title.text = text.value

text.on_change('value', update_title)

# # Set up layouts and add to document
inputs = widgetbox(text, names)

curdoc().add_root(row(inputs, p, width=800))
curdoc().title = "Sliders"

Upvotes: 0

Views: 2454

Answers (1)

bigreddot
bigreddot

Reputation: 34568

Typically you use LabelSet by configuring it with the same data source as some glyph renderer. I find whenever sharing column data sources, its best to just also create them explicitly. Here is an updated version of your code that renders:

# interactive widget bokeh figure
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Range1d, LabelSet, Label
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure

# data
x = [-4, 3, 2, 4, 10, 11, -2, 6]
y = [-3, 2, 2, 9, 11, 12, -5, 6]
names = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
colors =['r', 'y', 'y', 'r', 'g', 'g', 'g', 'g']

# create a CDS by hand
source = ColumnDataSource(data=dict(x=x, y=y, names=names, colors=colors))

p = figure(plot_height=400, plot_width=400, title="a little interactive chart",
           tools="crosshair,pan,reset,save,wheel_zoom",
           x_range=[-10, 10], y_range=[-10, 10])

# pass the CDS here, and column names (not the arrays themselves)
p.circle('x', 'y', fill_color="red", line_color="red", size=6, source=source)

# pass the CDS here too
labels = LabelSet(x='x', y='y', text='names', level='glyph',
         x_offset=5, y_offset=5, source=source)
p.add_layout(labels)

# Set up widgets
text = TextInput(title="title", value='a little interavtive chart')

# Set up callbacks
def update_title(attrname, old, new):
    p.title.text = text.value

text.on_change('value', update_title)

# # Set up layouts and add to document
inputs = widgetbox(text)

curdoc().add_root(row(inputs, p, width=800))
curdoc().title = "Sliders"

I also removed names from the widgetbox because widget boxes can only contain widget models. Maybe you intend to use the names in a Select widget or something?

Upvotes: 1

Related Questions