0
votes

I am quite new to bokeh and I have been trying to map different positions around London using gmap and show the price when Hover the mouse. However, I don't know why the Hovertools show '???'. Here is my code:

from bokeh.models import CustomJS, ColumnDataSource, CheckboxGroup, Column, Row
from bokeh.models import GMapOptions,PanTool, BoxSelectTool, CustomJSFilter, HoverTool, WheelZoomTool, CustomJS, ColumnDataSource
from bokeh.plotting import gmap
from bokeh.plotting import figure, show
import pandas as pd

df_map = pd.DataFrame({'y':[51.516568,51.517134,51.516361],'x' : [0.074812,-0.075898,-0.075888],'Price': [100,200,300],'Station':['Aldgate','Paddington','Euston']})
data_source = ColumnDataSource(df_map)
source = ColumnDataSource(dict(x=[],y=[],price =[]))
## Initiate Google Map
map_options = GMapOptions(lat=51.509865, lng=-0.118092, map_type="roadmap", zoom=10)
plot = gmap("GMAP_TOKEN_HERE", map_options, title="London Properties Map")

plot.circle('x','y',source = source)
## Add tools
TOOLTIPS = [
    ("Price", "@price"),
]
plot.add_tools(HoverTool(tooltips = TOOLTIPS))

## Callback function for select box
callback = CustomJS(args = {'source': source, 'data_source': data_source},
code = """
var data = data_source.data;
var s_data = source.data;

var x_data = data['x'];
var y_data = data['y'];
var select_vals = cb_obj.active.map(x => cb_obj.labels[x]);

var Nearest_tube = data['Station'];

var x = s_data['x'];
x.length = 0;
var y = s_data['y'];
y.length = 0;
var price = s_data['price'];
price.length = 0;

for (var i = 0; i < x_data.length; i++){
    if(select_vals.indexOf(Nearest_tube[i]) >= 0){
        x.push(x_data[i]);
        y.push(y_data[i]);
        price.push(price[i]);
    }
}
source.change.emit();
""")
chkbxgrp = CheckboxGroup(labels = ['Aldgate','Paddington','Euston'], active=[])
chkbxgrp.js_on_change('active', callback)
layout = Row(chkbxgrp, plot)
show(layout)

Any help would be appreciated. Thank you.

1
Take a careful look at this line in your code: price.push(price[i]);. - Eugene Pakhomov
Thank @EugenePakhomov for noticing that mistake. The code works great now after I changed to price.push(price_data[i]) after changing the name when defining the variable var price_data = s_data['price]. - Nguyen Quang

1 Answers

0
votes

The working code for London Bokeh Interactive map with Checkbox filter is as follow:

from bokeh.models import CustomJS, ColumnDataSource, CheckboxGroup, Column, Row
from bokeh.models import GMapOptions,PanTool, BoxSelectTool, CustomJSFilter, HoverTool, WheelZoomTool, CustomJS, ColumnDataSource
from bokeh.plotting import gmap

from bokeh.plotting import figure, show
import pandas as pd

df_map = pd.DataFrame({'y':[51.516568,51.517134,51.516361],'x' : [0.074812,-0.075898,-0.075888],'Price': [100,200,300],'Station':['Aldgate','Paddington','Euston']})
data_source = ColumnDataSource(df_map)
source = ColumnDataSource(dict(x=[],y=[],price =[]))
map_options = GMapOptions(lat=51.509865, lng=-0.118092, map_type="roadmap", zoom=10)
plot = gmap("GOOGLE_MAP_API_HERE", map_options, title="London Properties Map")

plot.circle('x','y',source = source)

TOOLTIPS = [
    ("Price", "@price"),
]
plot.add_tools(HoverTool(tooltips = TOOLTIPS))

callback = CustomJS(args = {'source': source, 'data_source': data_source},
code = """
var data = data_source.data;
var s_data = source.data;

var x_data = data['x'];
var y_data = data['y'];
var price_data = data['Price']
//var select_vals = cb_obj.value
var select_vals = cb_obj.active.map(x => cb_obj.labels[x]);

var Nearest_tube = data['Station'];

var x = s_data['x'];
x.length = 0;
var y = s_data['y'];
y.length = 0;
var price = s_data['price'];
price.length = 0;

for (var i = 0; i < x_data.length; i++){
    if(select_vals.indexOf(Nearest_tube[i]) >= 0){
        x.push(x_data[i]);
        y.push(y_data[i]);
        price.push(price_data[i]);
    }
}
source.change.emit();
""")
chkbxgrp = CheckboxGroup(labels = ['Aldgate','Paddington','Euston'], active=[])
chkbxgrp.js_on_change('active', callback)
layout = Row(chkbxgrp, plot)
show(layout)