Plot multiple lines with Python Bokeh fom the same dataset

1.4k Views Asked by At

Is there a possibility to achive plots like sample1 with Bokeh? Sample1 was created with Matplotlib. My goal is to plot multiple short lines which are separated from each other on the map. But the lines share the same source and are just different parts from the source within.

I already wrote a small script but with not so great results... (see Sample2). My skript draws 3 different lines on the map. Unfortunally the lines are linked together.

In Matplotlib it worked with for loops. But in Bokeh I try to use a slider to chose interactivly which data I like to see.

Sample1

Sample1

Sample2

Sample2

Here is my code:

from bokeh.io import output_file, show
from bokeh.models import ColumnDataSource, GMapOptions, CustomJS
from bokeh.plotting import gmap, ColumnDataSource, figure
from bokeh.layouts import column, row
from bokeh.models.widgets import RangeSlider 
import numpy as np

# data set
lon = [[48.7886, 48.7887, 48.7888, 48.7889, 48.789], 
        [48.7876, 48.7877, 48.78878, 48.7879, 48.787], 
        [48.7866, 48.7867, 48.7868, 48.7869, 48.786]]
lat = [[8.92, 8.921, 8.922, 8.923, 8.924],
        [8.91, 8.911, 8.912, 8.913, 8.914],
        [8.90, 8.901, 8.902, 8.903, 8.904]]

# convert data set in 1D for callback function (JS slice)
lat1D = []
lon1D = []
for k in range(len(lon)):
    lat1D += lat[k]
    lon1D += lon[k]

# define source and map
source = ColumnDataSource(data = {'x': lon1D, 'y': lat1D})

map_options = GMapOptions(lat=48.7886, lng=8.92, map_type="satellite", zoom=13)

p = gmap("MY_API_KEY", map_options, title="Trajectory Map")

# plot lines on map
# for loops do not work like in matplotlib...
for j in range(0, len(lon1D), len(lon)):
    for i in range(j, j + len(lon)):
        p.line('y', 'x', source=source, line_width=0.4)

# slider to limit plotted data
range_slider = RangeSlider(title="Data Range Slider: ", start=0, end=len(lon1D), value=(0, len(lon1D)), step=1) 

callback = CustomJS(args=dict(source=source, slider=range_slider, long=lon1D, lati=lat1D, lenght=len(lon)), code="""
    var data = source.data;
    const start = slider.value[0];
    const end = slider.value[1];
    
    data['x'] = long.slice(start, end)
    data['y'] = lati.slice(start, end)

    source.change.emit();
    """)

range_slider.js_on_change('value', callback)

# Layout to plot and output
layout = row(
    p, range_slider)

output_file("diag_plot_bike_data.html")

show(layout)
1

There are 1 best solutions below

2
On

Anything that can be plotted with Matplotlib, can be plotted with Bokeh. Sometimes with a bit more code, sometimes with a bit less.

There are too many things going on in your code, so I'll answer in plain text: