I have a large dataset from which I am interested in this part:
temp lat long
7.1 47 13
19 49 16
I tried using folium:
import requests
from xml.etree import ElementTree
import folium
from folium.plugins import MarkerCluster
MarkerCluster()
map2 = folium.Map(location=[47.031, 13.001999], tiles='CartoDB dark_matter', zoom_start=11)
marker_cluster = folium.plugins.MarkerCluster().add_to(map2)
But I get SyntaxError: unexpected EOF while parsing.
Then I tried using bokeh by copy-pasting an Internet example just to see if it works:
from bokeh.io import output_file, output_notebook, show
from bokeh.models import (
GMapPlot, GMapOptions, ColumnDataSource, Circle, LogColorMapper, BasicTicker, ColorBar,
DataRange1d, PanTool, WheelZoomTool, BoxSelectTool
)
from bokeh.models.mappers import ColorMapper, LinearColorMapper
from bokeh.palettes import Viridis5
map_options = GMapOptions(lat=37.88, lng=-122.23, map_type="roadmap", zoom=6)
plot = GMapPlot(
x_range=bokeh.Range1d(), y_range=bokeh.Range1d(), map_options=map_options
)
plot.title.text = "Hey look! It's a scatter plot on a map!"
show(plot)
But I get NameError: name 'bokeh' is not defined.
Is there any other way to plot a point or to fix the errors?
I tried to reproduce your Folium example with the following code :
from folium.plugins import MarkerCluster
m = folium.Map(location=[47.031, 13.001999], zoom_start=5)
marker_cluster = MarkerCluster().add_to(m)
folium.Marker(
location=[47.031, 13.001999],
popup='Add popup text here.',
icon=folium.Icon(color='green', icon='ok-sign'),
).add_to(marker_cluster)
m
It works just well :
Maybe there is another part of your code which was triggering the EOS error. An EOS error usually occurs because of missing commas, parenthesis etc.
If you are interested in the different types of folium Markers, there is an official Notebook with interesting examples.
Related
I am trying to use hvplot.line to plot 2 y variables in a line chart. My goal is to format the hover text to some format I want (say 1 decimal). I used the standard method to format them in bokeh's hovertool and try to pass it with ".opts(tools=)".
But the formatting does not reflect in the plot. I specified the format should '0.0',but the hover text still shows 3 decimal. What did I do wrong?
My code looks like something below:
import pandas as pd
import numpy as np
import hvplot.pandas
hvplot.extension('bokeh')
from numpy import random
from bokeh.models import HoverTool
df=pd.DataFrame({'length':np.linspace(0,4000,6),
'slope':np.linspace(1.7,2.4,6),
'Direction':np.linspace(1.2,-0.5,6),
'clearance':random.rand(6),
'weight':random.rand(6)},)
hover=HoverTool(tooltips=[('clearance','#clearance{0.0}'),('weight','#weight{0.0}')])
df.hvplot.line(x='length',y=['slope','Direction'],invert=True,hover_cols=['clearance','weight']).opts(tools=[hover])
But if I reduce the number of y variable to just 1. It works fine.
Replace the last line of code to be:
df.hvplot.line(x='length',y=['Direction'],invert=True,hover_cols=['clearance','weight']).opts(tools=[hover])
You can pass the tools to the plot call as a keyword argument.
Change your code
# df.hvplot.line(x='length',y=['slope','Direction'], hover_cols=['clearance','weight'], invert=True).opts(tools=[hover])
df.hvplot.line(x='length',y=['slope','Direction'], hover_cols=['clearance','weight'], tools=[hover], invert=True)
and your hovertool with your formatter is applied.
Minimal Example
import hvplot.pandas
import numpy as np
import pandas as pd
from bokeh.models import HoverTool
hvplot.extension('bokeh')
df=pd.DataFrame({
'length':np.linspace(0,4000,6),
'slope':np.linspace(1.7,2.4,6),
'Direction':np.linspace(1.2,-0.5,6),
'clearance':np.random.rand(6),
'weight':np.random.rand(6)}
)
hover=HoverTool(tooltips=[('clearance','#clearance{0.0}'),('weight','#weight{0.0}')])
df.hvplot.line(
x='length',
y=['slope','Direction'],
hover_cols=['clearance','weight'],
tools=[hover],
invert=True
)
Output
When I zoom out the following Bokeh plot:
A bunch of whitespace is added to both sides of the data:
How can I make it so that the right-hand side of the plot is fixed, so that zooming out will only create whitespace on the left-hand side? For example, this is my desired zoom-out look:
This is the code that initializes the plot:
from bokeh.plotting import figure, curdoc
from bokeh.driving import linear
from bokeh.models.tools import PanTool, WheelZoomTool
p = figure(sizing_mode="stretch_both", y_axis_location="right", x_axis_type="datetime")
pan_tool = p.select(dict(type=PanTool))
pan_tool.dimensions="width"
zoom_tool = p.select(dict(type=WheelZoomTool))
zoom_tool.dimensions="width"
This can be done with a CustomJS callback. Define a ColumnDataSource as source and look for the maximum x value on thof the source. If you have multiple renderers or multiple sources, you have to find the mximum of the maximums.
Minimal Example
from bokeh.plotting import show, figure, output_notebook
from bokeh.models import CustomJS, Line, ColumnDataSource
output_notebook()
p = figure(width=500, height=300)
source = ColumnDataSource(dict(x=data, y=data))
p.line(x='x', y='y', source=source)
callback = CustomJS(
args=dict(p=p, source=source),
code="""
p.x_range.end = Math.max(...source.data['x'])
p.change.emit();
"""
)
p.x_range.js_on_change("end", callback)
show(p)
I'm learning Python applied to data science and I'm trying to create an interactive map of my city, Madrid (Spain), showing the last election results. All I'm doing is in this GitHub link:
https://github.com/BernardoJoseLlamasVerna/Madrid_Elections_2021
You will see draft operations and looking for the best way to represent my data on a map:
https://github.com/BernardoJoseLlamasVerna/Madrid_Elections_2021/blob/main/Madrid_Elections_2021.ipynb
I'm following an example found on Internet about Wisconsin elections and fixes perfectly with what I would like to do with my data. I have downloaded it and stored on my repo to show you what I'm trying:
https://github.com/BernardoJoseLlamasVerna/Madrid_Elections_2021/blob/main/maps.ipynb
I've tried to do the same with my data, but nothing appears (even errors). The code is as follows:
from bokeh.io import output_notebook
from bokeh.plotting import figure, ColumnDataSource
from bokeh.io import output_notebook, show, output_file
from bokeh.plotting import figure
from bokeh.models import GeoJSONDataSource, LinearColorMapper, ColorBar, HoverTool
from bokeh.palettes import brewer
output_notebook()
import json
# res_w_states["clinton_share"] = res_w_states["clinton"] / res_w_states["total"]
#Convert data to geojson for bokeh
wi_geojson=GeoJSONDataSource(geojson=data.to_json())
color_mapper = LinearColorMapper(palette = brewer['RdBu'][10], low = 0, high = 1)
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8,width = 500, height = 20,
border_line_color=None,location = (0,0), orientation = 'horizontal')
hover = HoverTool(tooltips = [ ('Municipio','#Municipio'),('P.P.', '#P.P.'),
('P.S.O.E.','#P.S.O.E.'),
('Votos Totales','#Votos Totales')])
p = figure(title="Elecciones Madrid 2021", tools=[hover])
p.patches("xs","ys",source=wi_geojson,
fill_color = {'field' :'P.P.', 'transform' : color_mapper})
p.add_layout(color_bar, 'below')
show(p)
I've been analysing wi_geojson comparing between mine and what I copied and they seem to follow the same structure.
**QUESTION: ** anyone could give me a hint about what is wrong with my code, data, etc?
Thank you for your help.
P.D.: if anyone could also post a link with better interactive mapping, I would be so glad.
Thanks to mosc9575 I could manage a solution...
The problem was the Bokeh version (1.3.4); once updated (2.3.2) I could figure out my map. Now I have to fix the municipalities names XDD.
from bokeh.core.state import State
from bokeh.io import _CommsHandle, push_notebook
from bokeh.embed import notebook_div
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-4-b18f604973b2> in <module>()
----> 1 from bokeh.core.state import State
2 from bokeh.io import _CommsHandle, push_notebook
3 from bokeh.embed import notebook_div
ModuleNotFoundError: No module named 'bokeh.core.state'
from add_on import output_notebook, show_figure
from bokeh.io import output_notebook
from bokeh.plotting import Figure
from bokeh.models import ColumnDataSource
output_notebook()
The bokeh.core.state import State is the only import that doesnt work. The python versions are the same and there is no file with bokeh in the name. Anyone have any idea whats going on?
FYI: this I'm trying to create a bokeh graph where I can select data points with the lasso and get them back into jupyter notebook to for analysis. Here is the code I have to create the graphs, would love some insight on getting the datapoints back (assuming with Javascript).
import matplotlib as mpl
import bokeh.plotting as bpl
import bokeh.models as bmo
from bokeh.models import CategoricalColorMapper, ContinuousColorMapper
TOOLS="hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select,"
def graph_bokeh(algorithm,coordinate_df,metric):
source = bpl.ColumnDataSource(coordinate_df)
# color_map = bmo.CategoricalColorMapper(factors=coordinate_df[metric].unique())
# colors = {1:'red',0:'grey'}
if metric != 'LengthOfStayDaysNBR':
color_mapper = CategoricalColorMapper(palette=['red','grey'])#,factors = metric)
else:
color_mapper = ContinuousColorMapper(palette='Magma256', low=min(coordinate_df[metric]), high=max(coordinate_df[metric]))
bokeh_graph = figure(width=250, height = 250, title = '{}'.format(str(algorithm)[:3]),tools=TOOLS)
bokeh_graph.scatter('x-{}'.format(str(algorithm)[:3]),'y-{}'.format(str(algorithm)[:3])\
,color={'field': metric,'transform': color_mapper}\
, legend = metric, source = source)
return bokeh_graph
for metric in metrics:
bokeh_graphs = {}
for i,algorithm in enumerate(algorithms):
bokeh_graphs[i+1] = graph_bokeh(algorithm,df_algs,metric)
graph_list = []
for k,v in bokeh_graphs.items():
if k%2 == 1 and k!= len(bokeh_graphs):
graph_list.append([bokeh_graphs[k],bokeh_graphs[k+1]])
elif k%2 == 1 and k == len(bokeh_graphs):
graph_list.append([bokeh_graphs[k],None])
p = gridplot(graph_list)
show(p)
(sorry for three/four part question):
I'm having trouble with the color gradient for the lengthofstay metric (a third column i would like to color the x/y coordinates by)
color_mapper = ContinuousColorMapper(palette='Magma256', low=min(coordinate_df[metric]), high=max(coordinate_df[metric]))
always outputs the blue color gradient (no matter what palette i specify)
Lastly,
the graphs open in internet explorer, and i would like chrome.
import webbrowser
webbrowser.register("chrome", None)
doesnt seem to work,
neither does
show(browser='chrome')
That module moved to bokeh.io some time ago:
In [3]: from bokeh.io.state import State
In [4]:
Can I ask why you think you need to use State directly? It's not something I would really consider necessary for normal users to ever use. It mostly exists to facilitate testing.
How do you create a multiline plot title in bokeh?... same question as https://github.com/bokeh/bokeh/issues/994
Is this resolved yet?
import bokeh.plotting as plt
plt.output_file("test.html")
plt.text(x=[1,2,3], y = [0,0,0], text=['hello\nworld!', 'hello\nworld!', 'hello\nworld!'], angle = 0)
plt.show()
Additionally, can the title text string accept rich text?
In recent versions of Bokeh, labels and text glyphs can accept newlines in the text, and these will be rendered as expected. For multi-line titles, you will have to add explicit Title annotations for each line you want. Here is a complete example:
from bokeh.io import output_file, show
from bokeh.models import Title
from bokeh.plotting import figure
output_file("test.html")
p = figure(x_range=(0, 5))
p.text(x=[1,2,3], y = [0,0,0], text=['hello\nworld!', 'hello\nworld!', 'hello\nworld!'], angle = 0)
p.add_layout(Title(text="Sub-Title", text_font_style="italic"), 'above')
p.add_layout(Title(text="Title", text_font_size="16pt"), 'above')
show(p)
Which produces:
Note that you are limited to the standard "text properties" that Bokeh exposes, since the underlying HTML Canvas does not accept rich text. If you need something like that it might be possible with a custom extension
You can add a simple title to your plot with this:
from bokeh.plotting import figure, show, output_file
output_file("test.html")
p = figure(title="Your title")
p.text(x=[1,2,3], y = [0,0,0], text=['hello\nworld!', 'hello\nworld!', 'hello\nworld!'], angle = 0)
show(p)
Addendum
Here is a working example for plotting a pandas dataframe for you to copy/paste into a jupyter notebook. It's neither elegant nor pythonic. I got it a long time ago from various SO posts. Sorry, that I don't remember which ones anymore, so I can't cite them.
Code
# coding: utf-8
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
import pandas as pd
import numpy as np
# Create some data
np_arr = np.array([[1,1,1], [2,2,2], [3,3,3], [4,4,4]])
pd_df = pd.DataFrame(data=np_arr)
pd_df
# Convert for multi-line plotting
data = [row[1].as_matrix() for row in pd_df.iterrows()]
num_lines = len(pd_df)
cols = [pd_df.columns.values] * num_lines
data
# Init bokeh output for jupyter notebook - Adjust this to your needs
output_notebook()
# Plot
p = figure(plot_width=600, plot_height=300)
p.multi_line(xs=cols, ys=data)
show(p)
Plot