First time posting in stackoverflow. Hope you guys are doing well.
Recently, I am trying to create a filterable Bokeh graph to graph a US map base on the filter an user select. However, when I try to fit a geometry to ColumnDataSource. It is giving me an error: TypeError: Object of type Polygon is not JSON serializable
when I run show(figure)
The code below shows how I want to update geometry to ColumnDataSource and I get an error
# <------- This is where the graph starts------->
# reset the graph
reset_output()
# import data
data = gpd.read_file("/Users/xxxx/Desktop/cb_2015_us_state_500k/cb_2015_us_state_500k.shp", encoding="utf-8")
data1 = data[~data.STUSPS.isin(['AK','AS', 'GU', 'HI', 'PR','MP', 'VI'])]
data2 = data[data.STUSPS.isin(['TX', 'UT'])]
# get a list of unique value
unique_state = sorted(list(data2.NAME.unique()))
select = Select(title="State", options=unique_state)
# get data into ColumnDataSource
source=ColumnDataSource(ColumnDataSource.from_df(data2.loc[:]))
# crate filtered dataframe
filteredSource = ColumnDataSource(data=dict(STUSPS=[],NAME=[],ALAND=[]))
columns = [TableColumn(field="NAME",title="NAME",sortable=True),
TableColumn(field="STUSPS",title="STUSPS",sortable=True),
TableColumn(field="ALAND",title="ALAND",sortable=True),
TableColumn(field="geometry",title="geometry",sortable=True)]
data_table=DataTable(source=filteredSource,columns=columns, width=800 )
# <---- Call back starts ---->
callback = CustomJS(args=dict(source=source,
filteredSource=filteredSource,
data_table=data_table), code="""
var data = source.data;
var f = cb_obj.value;
var d2 = filteredSource.data;
d2['STUSPS']=[]
d2['NAME']=[]
d2['ALAND']=[]
d2['geometry']=[]
for(i = 0; i < data['NAME'].length;i++){
if(data['NAME'][i]==f){
d2['STUSPS'].push(data['STUSPS'][i])
d2['NAME'].push(data['NAME'][i])
d2['ALAND'].push(data['ALAND'][i])
d2['geometry'].push(data['geometry'][i])
}
}
filteredSource.change.emit()
// trigger change on datatable
data_table.change.emit()
""")
select.js_on_change('value',callback)
layout = column(widgetbox(select, data_table))
# output_file("filter.html", title="filter example")
show(layout)
Afterwards, I saw an example directly fitting shape file to dictionary or dataframe which may solve the problem. Here is the link: Bokeh Mapping Counties However, when I using the code to graph it. it is giving me
ValueError: Out of range float values are not JSON compliant
This is the code I run:
import shapefile
import itertools
shp = open("/Users/xxxx/Desktop/cb_2015_us_state_500k/cb_2015_us_state_500k.shp", "rb")
dbf = open("/Users/xxxx/Desktop/cb_2015_us_state_500k/cb_2015_us_state_500k.dbf", "rb")
sf = shapefile.Reader(shp=shp, dbf=dbf)
lats = []
lons = []
ct_name = []
st_id = []
ct_state_name = []
for shprec in sf.shapeRecords():
st_id.append(int(shprec.record[0]))
ct_name.append(shprec.record[5])
ct_state_name.append(shprec.record[4])
lat, lon = map(list, zip(*shprec.shape.points))
indices = shprec.shape.parts.tolist()
lat = [lat[i:j] + [float('NaN')] for i, j in zip(indices, indices[1:]+[None])]
lon = [lon[i:j] + [float('NaN')] for i, j in zip(indices, indices[1:]+[None])]
lat = list(itertools.chain.from_iterable(lat))
lon = list(itertools.chain.from_iterable(lon))
lats.append(lat)
lons.append(lon)
map_data = pd.DataFrame({'x': lats, 'y': lons, 'state': st_id, 'county_name': ct_name, 'ct_state_name': ct_state_name})
map_data_m = map_data[map_data.ct_state_name.isin(['NJ'])]
source = ColumnDataSource(map_data_m)
TOOLS="pan,wheel_zoom,box_zoom,reset,hover,save"
p = figure(title="Title", tools=TOOLS,
x_axis_location=None, y_axis_location=None)
p.grid.grid_line_color = None
p.patches('x', 'y', source=source,
fill_color='color', fill_alpha=0.7,
line_color="white", line_width=0.5)
show(p)
anyone who is able to help me to resolve either of the question? I have been stuck for few days. Thanks a lot!