Skillversitas

ColumnDataSource

ColumnDataSource (CDS) is Bokeh's data model: a dictionary of columns where every column has the same length. Glyphs reference columns by name, which lets one glyph respond to data updates without re-creating it - the foundation of interactive and streaming plots.

Creating a CDS

from bokeh.plotting import figure
from bokeh.models import ColumnDataSource

x = [1, 2, 3, 4]
y = [4, 5, 6, 5]
names = ["a", "b", "c", "d"]

source = ColumnDataSource(data={
    "x": x,
    "y": y,
    "name": names,
})

p = figure()
p.circle("x", "y", source=source, size=10)
p.circle("x", "y", source=source, color="red")  # second renderer on same data

Column References and Styling

p.circle("x", "y", source=source,
         color="navy",
         size={"field": "radius"},      # per-point size from a column
         fill_alpha={"field": "alpha"})

Building from pandas

import pandas as pd

df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6], "grp": ["A", "B", "A"]})
source = ColumnDataSource(df)   # DataFrame columns become CDS columns

Updating Data Live

import time

# replace all data:
source.data = {"x": [5, 6], "y": [7, 8], "name": ["e", "f"]}

# stream new rows (keeps last N):
source.stream({"x": [7], "y": [9], "name": ["g"]}, max_size=1000)

# patch a specific row (index, {col: value}):
source.patch([(1, {"y": 99})])

Reading Selected Points

from bokeh.models import BoxSelectTool

p.select(type=BoxSelectTool).on_select_callback = None  # default: client-side
# the selected indices are available server-side via:
selected = p.select(type=BoxSelectTool).selected
print(selected.indices)
print(source.selected["data"])  # dict of selected column values

When to Use a CDS

  • Always, for interactive plots - it is what makes updates cheap.
  • When multiple glyphs share data (one CDS, many renderers).
  • When you need hover tooltips on named columns (@name).

Summary

ColumnDataSource is a dict-of-equal-length-columns that glyphs reference by name. Create it from plain dicts or pandas, style per-point with {"field": col} references, and update it with data replacement, stream(), or patch() to drive live plots. Selections are readable from the source's selected property.