I want to plot shapely polygons, stored in GeoDataFrame on map with Bokeh.
1. What type of Glyph to choose to plot polygons?
2. How to pass the data to the Glyph?
I am trying to do it in the following way:
from bokeh.models import GMapOptions, PanTool, WheelZoomTool,
WheelPanTool, BoxSelectTool, BoxEditTool
from bokeh.plotting import gmap
p = gmap(api_key, map_options, title= f'offer {str(sales_id)} ')
map_options = GMapOptions(lat = lats_s, lng = lons_s,
map_type="roadmap", zoom=12)
api_key = 'my_api_key'
x, y = some_shapely_polygon.exterior.coords.xy
x = x.tolist()
y = y.tolist()
source = ColumnDataSource(data=dict(
x=x, y=y,))
p.patches('x', 'y', source=source,
fill_alpha=0.8, line_color="black", line_width=0.3)
show(p)
I get an error:
"Javascript Error: Invalid array length"
When I pass son other data with Circles it all works well, I I can not plot Ploygons.
Thank you!
These examples work for me. Replace map.shp with your filename. Works with Bokeh v1.0.4. Run with: python map.py
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
import geopandas as gp
import shapely
sf = gp.read_file('map.shp')
x, y = [], []
[(x.append(list(polygon.exterior.coords.xy[0])), y.append(list(polygon.exterior.coords.xy[1]))) for polygon in sf['geometry'] if type(polygon.boundary) == shapely.geometry.linestring.LineString ]
p = figure(title = "A map from Shapefile", plot_width = 800)
p.patches('x', 'y', source = ColumnDataSource(dict(x = x, y = y)), line_color = "white", line_width = 0.5)
show(p)
or
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
import geopandas as gp
def getPolyCoords(row, geom, coord_type):
if coord_type == 'x':
return list(row[geom].exterior.coords.xy[0])
elif coord_type == 'y':
return list(row[geom].exterior.coords.xy[1])
gdf = gp.GeoDataFrame.from_file('map.shp')
gdf['x'] = gdf.apply(getPolyCoords, geom = 'geometry', coord_type = 'x', axis = 1)
gdf['y'] = gdf.apply(getPolyCoords, geom = 'geometry', coord_type = 'y', axis = 1)
p_df = gdf.drop('geometry', axis = 1).copy()
p = figure(title = "A map from Shapefile", plot_width = 800)
p.patches('x', 'y', source = ColumnDataSource(p_df), line_color = "white", line_width = 0.5)
show(p)
Related
I'm trying to assign two different color palettes to my data set below based on gender. It's important to see both graphs side by side:
enter image description here
This is my code so far:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
g = sns.catplot(data = run_data,
x = 'Disc_Age',
kind = 'count',
col = 'SEX',
aspect = 2);
h = sns.catplot(data = run_data,
x = 'Disc_Age',
kind = 'count',
col = 'SEX',
height = 6,
palette=(sns.color_palette('rocket', 11)))
h.set_xticklabels(rotation=45, horizontalalignment='right');
Could you please help me see where I went wrong?
EDIT:
I added this to the code and this has gotten me the closest to what I want (except I don't have separate seaborn palettes for males and females):
palette = {
'M': 'tab:blue',
'F': 'tab:red',
}
h = sns.catplot(data = run_data,
x = 'Disc_Age',
kind = 'count',
col = 'SEX',
aspect = 2,
hue = 'SEX',
palette = palette)
h.set_xticklabels(rotation = 45,
horizontalalignment = 'right',
fontsize = 18);
plt.show()
enter image description here
I want to adjust the bar spacing and also the color so changes for each bar.
I tried making a list for the colors, but it does not seem to work
import numpy as np
import matplotlib.pyplot as plt
# creating the dataset
data = {'Kombineret bøjning og tryk':0.20, 'Kombineret bøjning og træk':0.15, 'Stabilitetsproblemer (udbøjning, y-akse)':0.30,
'Stabilitetsproblemer (udbøjning, z-akse)':0.35}
y_pos = np.arange(len(data))
courses = list(data.keys())
values = list(data.values())
c = ['red', 'yellow', 'black', 'blue', 'orange']
fig = plt.figure(figsize = (10, 5))
# creating the bar plot
plt.barh(courses, values, height=0.1, color ='c', align='edge')
plt.yticks(y_pos, data)
plt.xlim(0,1)
plt.xlabel("Udnyttelsesgrad < 1,0")
plt.title("Udnyttelser")
plt.show()
Making a list, did not work.
I'm trying to make a table to represent the relationship between categorical values based on their count. This is my current code:
source = ColumnDataSource(df)
mapper = LinearColorMapper(palette=brewer['YlGnBu'][4], low=df['count'].min(), high=df['count'].max())
tooltips = [
("Resource", "#org:resoure"),
("Activity", "#concept:name"),
("Count", "#count"),
]
p = figure(plot_width=df['org:resource'].nunique()*180, plot_height=df['concept:name'].nunique()*100, title="US Unemployment 1948—2016",
y_range=df['concept:name'].unique(), x_range=df['org:resource'].unique(),x_axis_location="above", tooltips=tooltips)
p.rect(y="concept:name", x="org:resource", width=1, height=1, source=source,
line_color=None, fill_color=transform('count', mapper))
color_bar = ColorBar(color_mapper=mapper, location=(0, 0),
ticker=BasicTicker(),
formatter=PrintfTickFormatter(format="%d%%"))
p.add_layout(color_bar, 'right')
p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_text_font_size = "13px"
p.axis.major_label_standoff = 0
p.xaxis.major_label_orientation = 0
output_notebook()
show(p)
However, this code produces a grid that does not suite categorical values. How can I shift the grid down?
current visual produced by code
You can achieve this using a FixedTicker.
Here is a very basic example where p.rect() is used.
old
new
The code is very similar, except the ticks are shifted by 0.5 on both axis in the new version using the FixedTicker I mentioned.
old
from bokeh.plotting import figure, output_file, show
data = [1, 5]
plot = figure(plot_width=300, plot_height=300)
plot.rect(x=data, y=data, width=1, height=1, color="#CAB2D6")
show(plot)
new
from bokeh.plotting import figure, output_file, show
from bokeh.models import FixedTicker
data = [1, 5]
plot = figure(plot_width=300, plot_height=300)
plot.rect(x=data, y=data, width=1, height=1, color="#CAB2D6")
_max = max(data)
plot.xaxis.ticker = FixedTicker(ticks=[x+0.5 for x in range(_max+1)])
plot.yaxis.ticker = FixedTicker(ticks=[x+0.5 for x in range(_max+1)])
show(plot)
Creating 2D scatter plot by plotly can be done following the example from:
https://plot.ly/python/line-and-scatter/
However, is there any easy way to add arrows below the x axis?
You could use Plotly's annotations without text.
import plotly
import numpy as np
plotly.offline.init_notebook_mode()
N = 1000
data = [plotly.graph_objs.Scatter(x=np.random.randn(N),
y=np.random.randn(N),
mode = 'markers'
)
]
xstart = -2
xmax = 3.5
xmin = -3.5
padding = 0.05
ypos = -0.1
layout = plotly.graph_objs.Layout(
xaxis=dict(range=[xmin, xmax]),
showlegend=False,
annotations=[
dict(
x=xmin,
y=ypos,
ax=xstart + padding,
ay=ypos,
xref='x',
axref='x',
yref='paper',
ayref='paper',
showarrow=True,
arrowhead=2,
arrowsize=1,
arrowwidth=3,
arrowcolor='#0000ff',
),
dict(
x=xmax,
y=ypos,
ax=xstart - padding,
ay=ypos,
xref='x',
axref='x',
yref='paper',
ayref='paper',
showarrow=True,
arrowhead=2,
arrowsize=1,
arrowwidth=3,
arrowcolor='#ff0000',
)
])
plotly.offline.iplot(plotly.graph_objs.Figure(data=data,
layout=layout))
So what I'd like to do is a simple figure with lines and circles like
http://docs.bokeh.org/en/latest/docs/quickstart.html#getting-started
but with labels which show after mouseover over the circles.
Would that be possible?
From what I understand HoverTool is what you are looking for. You can see an example of it being used on rect glyphs instead of circles (and lines) but that should be the final result.
Here's a modified version of the line example with circle glyphs and a hover tool:
from collections import OrderedDict
import numpy as np
from bokeh.plotting import *
from bokeh.models import HoverTool
x = np.linspace(0, 4*np.pi, 200)
y = np.sin(x)
output_file("line_dots.html", title="line.py example")
source = ColumnDataSource(
data=dict(
x=x,
y=y,
label=["%s X %s" % (x_, y_) for x_, y_ in zip(x, y)]
)
)
TOOLS="crosshair,pan,wheel_zoom,box_zoom,reset,hover,previewsave"
p = figure(title="simple line example", tools=TOOLS)
p.line('x', 'y', color="#2222aa", line_width=2, source=source)
p.circle('x', 'y', color="#2222aa", line_width=2, source=source)
hover =p.select(dict(type=HoverTool))
hover.tooltips = OrderedDict([
("index", "$index"),
("(xx,yy)", "(#x, #y)"),
("label", "#label"),
])
show(p)