Save plot data as csv

Here is a working example with Python 3.7.5 and Bokeh 1.4.0. Generate linked plots + TABLE displaying data + save button to export cvs of selected data

public github link to this jupyter notebook:

##environment report:

####virtual env python version:
Python 3.7.5
virtual env ipython version:
7.9.0

####watermark package reports:
bokeh 1.4.0
jupyter 1.0.0
numpy 1.17.4
pandas 0.25.3
rise 5.6.0
watermark 2.0.2

Generate linked plots + TABLE displaying data + save button to export cvs of selected data

“”"
from random import random

from bokeh.io import output_notebook
from bokeh.io import show

from bokeh.layouts import row
from bokeh.layouts import grid
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.models import Button
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
from bokeh.models import HoverTool
from bokeh.plotting import figure

create data

x = [random() for x in range(500)]
y = [random() for y in range(500)]

create first subplot

plot_width = 400
plot_height = 400

s1 = ColumnDataSource(data=dict(x=x, y=y))
fig01 = figure(
plot_width=plot_width,
plot_height=plot_height,
tools=[“lasso_select”, “reset”, “save”],
title=“Select Here”,
)
fig01.circle(“x”, “y”, source=s1, alpha=0.6)

create second subplot

s2 = ColumnDataSource(data=dict(x=, y=))

demo smart error msg: box_zoom, vs BoxZoomTool

fig02 = figure(
plot_width=400,
plot_height=400,
x_range=(0, 1),
y_range=(0, 1),
tools=[“box_zoom”, “wheel_zoom”, “reset”, “save”],
title=“Watch Here”,
)

corrected code - reference

fig02 = figure(plot_width=plot_width, plot_height=plot_height, x_range=(0, 1), y_range=(0, 1),

tools=[“pan”, “box_zoom”, “wheel_zoom”, “reset”], title=“Watch Here”)

fig02.circle(“x”, “y”, source=s2, alpha=0.6, color=“firebrick”)

create dynamic table of selected points

columns = [
TableColumn(field=“x”, title=“X axis”),
TableColumn(field=“y”, title=“Y axis”),
]

table = DataTable(
source=s2,
columns=columns,
width=400,
height=600,
sortable=True,
selectable=True,
editable=True,
)

fancy javascript to link subplots

js pushes selected points into ColumnDataSource of 2nd plot

inspiration for this from a few sources:

credit: User iolsmit - Stack Overflow via: python - Bokeh, lasso select to table update - Stack Overflow

credit: User Joris - Stack Overflow via: python - Get selected data contained within box select tool in Bokeh - Stack Overflow

s1.selected.js_on_change(
“indices”,
CustomJS(
args=dict(s1=s1, s2=s2, table=table),
code="""
var inds = cb_obj.indices;
var d1 = s1.data;
var d2 = s2.data;
d2[‘x’] =
d2[‘y’] =
for (var i = 0; i < inds.length; i++) {
d2[‘x’].push(d1[‘x’][inds[i]])
d2[‘y’].push(d1[‘y’][inds[i]])
}
s2.change.emit();
table.change.emit();

    var inds = source_data.selected.indices;
    var data = source_data.data;
    var out = "x, y\\n";
    for (i = 0; i < inds.length; i++) {
        out += data['x'][inds[i]] + "," + data['y'][inds[i]] + "\\n";
    }
    var file = new Blob([out], {type: 'text/plain'});
    
""",
),

)

create save button - saves selected datapoints to text file onbutton

inspration for this code:

credit: python - is there a way to save bokeh data table content - Stack Overflow

note: savebutton line var out = "x, y\\n"; defines the header of the exported file, helpful to have a header for downstream processing

savebutton = Button(label=“Save”, button_type=“success”)
savebutton.callback = CustomJS(
args=dict(source_data=s1),
code="""
var inds = source_data.selected.indices;
var data = source_data.data;
var out = “x, y\n”;
for (i = 0; i < inds.length; i++) {
out += data[‘x’][inds[i]] + “,” + data[‘y’][inds[i]] + “\n”;
}
var file = new Blob([out], {type: ‘text/plain’});
var elem = window.document.createElement(‘a’);
elem.href = window.URL.createObjectURL(file);
elem.download = ‘selected-data.txt’;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
“”",
)

add Hover tool

define what is displayed in the tooltip

tooltips = [
(“X:”, “@x”),
(“Y:”, “@y”),
(“static text”, “static text”),
]

fig02.add_tools(HoverTool(tooltips=tooltips))

things to try:

- display results

- demo linked plots

- demo zooms and reset

- demo hover tool

- demo table

-demo save selected results to file

layout = grid([fig01, fig02, table, savebutton], ncols=3)

output_notebook()
show(layout)
“”"

things to try:

- select random shape of blue dots with lasso tool in ‘Select Here’ graph

- only selected points appear as red dots in ‘Watch Here’ graph – try zooming, saving that graph separately

- selected points also appear in the table, which is sortable

- click the ‘Save’ button to export a csv

TODO: export from Bokeh to pandas dataframe

2 Likes