Plotting multiple states bokeh - bokeh

I'm trying to plot two things:
Counties for MD, VA, and DC
Lats/Longs for housing listings in that area (most expensive in a certain color
and least expensive in another color)
However, I'm having trouble with part 1, and cannot seem to plot the counties without getting the error message:
"Javascript error adding output!
Error: Error rendering Bokeh model: could not find tag with id: xxxxxxxxxxx
See your browser Javascript console for more details."
where xxxxx are numbers
from bokeh.io import show
from bokeh.models import (
ColumnDataSource,
HoverTool,
LogColorMapper)
from bokeh.palettes import Viridis6 as palette
from bokeh.plotting import figure
from bokeh.sampledata.us_counties import data as counties
from bokeh.sampledata.unemployment import data as unemployment
palette.reverse()
va_counties = {
code: county for code, county in counties.items() if county["state"] == "va"
}
md_counties = {
code: county for code, county in counties.items() if county["state"] == "md"
}
dc_counties = {
code: county for code, county in counties.items() if county["state"] == "dc"
}
va_county_xs = [county["lons"] for county in va_counties.values()]
va_county_ys = [county["lats"] for county in va_counties.values()]
md_county_xs = [county["lons"] for county in md_counties.values()]
md_county_ys = [county["lats"] for county in md_counties.values()]
dc_county_xs = [county["lons"] for county in dc_counties.values()]
dc_county_ys = [county["lats"] for county in dc_counties.values()]
va_county_names = [county['name'] for county in va_counties.values()]
md_county_names = [county['name'] for county in md_counties.values()]
dc_county_names = [county['name'] for county in dc_counties.values()]
#county_rates = [unemployment[county_id] for county_id in counties]
color_mapper = LogColorMapper(palette=palette)
va_source = ColumnDataSource(data=dict(
x=va_county_xs,
y=va_county_ys,
name=va_county_names,
))
md_source = ColumnDataSource(data=dict(
x=md_county_xs,
y=md_county_ys,
name=md_county_names,
))
dc_source = ColumnDataSource(data=dict(
x=dc_county_xs,
y=dc_county_ys,
name=dc_county_names,
))
TOOLS = "pan,wheel_zoom,reset,hover,save"
va = figure(
title="Texas Unemployment, 2009", tools=TOOLS,
x_axis_location=None, y_axis_location=None
)
va.grid.grid_line_color = None
md = figure(
title="Texas Unemployment, 2009", tools=TOOLS,
x_axis_location=None, y_axis_location=None
)
md.grid.grid_line_color = None
dc = figure(
title="Texas Unemployment, 2009", tools=TOOLS,
x_axis_location=None, y_axis_location=None
)
dc.grid.grid_line_color = None
va.patches('x', 'y', source=va_source,
fill_color={'field': 'rate', 'transform': color_mapper},
fill_alpha=0.7, line_color="white", line_width=0.5)
md.patches('x', 'y', source=md_source,
fill_color={'field': 'rate', 'transform': color_mapper},
fill_alpha=0.7, line_color="white", line_width=0.5)
dc.patches('x', 'y', source=dc_source,
fill_color={'field': 'rate', 'transform': color_mapper},
fill_alpha=0.7, line_color="white", line_width=0.5)
hover = p.select_one(HoverTool)
hover.point_policy = "follow_mouse"
hover.tooltips = [
("Name", "#name"),
("(Long, Lat)", "($x, $y)"),
]
show(va)
show(md)
show(dc)

Bokeh maintains an implicit "current document" and by default everything you make gets added to that. This makes it very simple to have a script that generates one HTML file, and especially makes usage in the Jupyter notebook much more simple and transparent. In general this is a net positive, but it does make certain other usage patterns need to be slightly more verbose. In particular in your case with multiple show calls, each call to show gets the same document which is probably not what you intend. The solution is to create and show each plot in order, and call reset_output in between. Additionally, you would really need to specify unique filenames for each separate output, by using output_file. Here is a small complete example:
from bokeh.io import output_file, reset_output, show
from bokeh.plotting import figure
# create and show one figure
p1 = figure(title="plot 1")
p1.circle([1,2,3], [4,6,5])
output_file("p1.html")
show(p1)
# clear out the "current document"
reset_output()
# create and show another figure
p2 = figure(title="plot 2")
p2.circle([1,2,3], [8,6,7])
output_file("p2.html")
show(p2)
There are other ways to do this by managing Bokeh Document objects explicitly yourself, but I would probably say this is the simplest to get started.

Related

How to create an custom entry/exit signal in VectorBT?

thanks for reading!
I'm trying to backtest a strategy that I wrote in Pinescrpt, and I struggle to create my entry conditions.
So this is the code
import numpy as np
import pandas as pd
import vectorbt as vbt
from datetime import datetime
from binance.client import Client
symbols=['SOLUSDT', 'BNBUSDT']
price =
vbt.BinanceData.download(symbols,
start= '5 days ago UTC',
end= 'Now UTC',
interval='30m', missing_index='drop'
).get(['High', 'Low', 'Open', 'Close'])
high = price[0]
low = price[1]
open = price[2]
close = price[3]
stoch = vbt.STOCH.run(
high=high,
low=low,
close = close,
k_window = 14
)
And I want to add
entries = abs(stoch.percent_k['SOLUSDT'] -
stoch.percent_k['SOLUSDT']) > 50 # (mi intention with abs is to get the absolute value)
exits = abs(stoch.percent_k['SOLUSDT'] -
stoch.percent_k['SOLUSDT']) < 5
portfolio = vbt.Portfolio.from_signals(price[3], entries, exits, init_cash=10000)
I pretend to trigger a short order in a symbol and a long order in the second simultaneously with those signals.
And if anyone has a recommendation about where to find educational resources about this particular package (besides the official web) is welcome. I have read the examples in the doc, but it still fills a bit too complex for my level.

Bokeh LabelSet x axis being datetime

I am new to Bokeh and looking for solution to label each data point. Replicating the examples shown in documents, I could not find solutions with X axis being datetime.
import pandas as mypd
from bokeh.models import LabelSet , ColumnarDataSource
from bokeh.plotting import figure, output_file, show
date_1 = ['2020-01-01', '2020-01-02','2020-01-03','2020-01-04','2020-01-05']
sal = mypd.DataFrame(date_1)
sal.columns = ["Date_1"]
sal['Sales'] = [15,25,36,17,4]
sal['Date_1'] = mypd.to_datetime(sal['Date_1'])
p= figure(x_axis_type = "datetime")
p.line(x =sal['Date_1'] ,y = sal['Sales'])
lab = LabelSet(x = sal['Date_1'], y = sal['Sales'], text = sal['Sales'])
p.add_layout(lab)
show(p)
It is throwing the error
ValueError: expected an element of either String, Dict(Enum('expr', 'field', 'value', 'transform'), Either(String, Instance(Transform), Instance(Expression), Float)) or Float, got 0 2020-01-01
I understand the error is because x axis take numerical data for labelset.
Is my understanding correct ?
If yes what is the workaround ?
I tried with similar queries but could not find a solution for myself.
Similar Query
And this
The simplest solution is to just use a common data source. It also prevents you from embedding the data twice.
import pandas as pd
from bokeh.models import LabelSet, ColumnDataSource
from bokeh.plotting import figure, show
sal = (pd.DataFrame({'Date_1': pd.to_datetime(['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04', '2020-01-05']),
'Sales': [15, 25, 36, 17, 4]})
.set_index('Date_1'))
ds = ColumnDataSource(sal)
p = figure(x_axis_type="datetime")
p.line(x='Date_1', y='Sales', source=ds)
lab = LabelSet(x='Date_1', y='Sales', text='Sales', source=ds)
p.add_layout(lab)
show(p)

Python ArcPy - Print Layer with highest field value

I have some python code that goes through layers in my ArcGIS project and prints out the layer names and their corresponding highest value within the field "SUM_USER_VisitCount".
Output Picture
What I want the code to do is only print out the layer name and SUM_USER_VisitCount field value for the one layer with the absolute highest value.
Desired Output
I have been unable to figure out how to achieve this and can't find anything online either. Can someone help me achieve my desired output?
Sorry if the code layout is a little weird. It got messed up when I pasted it into the "code sample"
Here is my code:
import arcpy
import datetime
from datetime import timedelta
import time
#Document Start Time in-order to calculate Run Time
time1 = time.clock()
#assign project and map frame
p =
arcpy.mp.ArcGISProject(r'E:\arcGIS_Shared\Python\CumulativeHeatMaps.aprx')
m = p.listMaps('Map')[0]
Markets = [3000]
### Centers to loop through
CA_Centers = ['Castro', 'ColeValley', 'Excelsior', 'GlenPark',
'LowerPacificHeights', 'Marina', 'NorthBeach', 'RedwoodCity', 'SanBruno',
'DalyCity']
for Market in Markets:
print(Market)
for CA_Center in CA_Centers:
Layers =
m.listLayers("CumulativeSumWithin{0}_{1}_Jun2018".format(Market,CA_Center))
fields = ['SUM_USER_VisitCount']
for Layer in Layers:
print(Layer)
sqlClause = (None, 'ORDER BY ' + 'SUM_USER_VisitCount') # + 'DESC'
with arcpy.da.SearchCursor(in_table = Layer, field_names = fields,
sql_clause = sqlClause) as searchCursor:
print (max(searchCursor))
You can create a dictonary that stores the results from each query and then print out the highest one at the end.
results_dict = {}
for Market in Markets:
print(Market)
for CA_Center in CA_Centers:
Layers =
m.listLayers("CumulativeSumWithin{0}_{1}_Jun2018".format(Market,CA_Center))
fields = ['SUM_USER_VisitCount']
for Layer in Layers:
print(Layer)
sqlClause = (None, 'ORDER BY ' + 'SUM_USER_VisitCount') # + 'DESC'
with arcpy.da.SearchCursor(in_table = Layer, field_names = fields,
sql_clause = sqlClause) as searchCursor:
print (max(searchCursor))
results_dict[Layer] = max(searchCursor)
# get key for dictionary item with the highest value
highest_count_layer = max(results_dict, key=results_dict.get)
print(highest_count_layer)
print(results_dict[highest_count_layer])

bokeh 0.12.10 not rendering Segments on GMapPlot

I am trying to display line segments on a map using GMapPlot. The lines flashes in red and then disappears, in jupyter notebook. This is my code (some decimals left out):
map_options = GMapOptions(lat=37.88, lng=-122.23, map_type="roadmap", zoom=10)
plot = GMapPlot(
x_range=DataRange1d(), y_range=DataRange1d(), map_options=map_options
)
source = ColumnDataSource( data = dict(
y=[ 37.762260 ],
x=[-121.96226],
ym01=[37.762290 ],
xm01=[-121.96189 ]
)
segment = Segment(x0="x", y0="y", x1="xm01", y1="ym01",line_color="green", line_width=100)
plot.add_glyph(source, segment)
plot.add_tools(PanTool(), WheelZoomTool(), BoxSelectTool())
output_notebook()
show(plot)
UPDATE This issue is resolved in https://github.com/bokeh/bokeh/pull/8240 which will be part of Bokeh 1.0
I've tried to reproduce with updated code:
from bokeh.io import show
from bokeh.models import GMapOptions, ColumnDataSource
from bokeh.plotting import figure, gmap
map_options = GMapOptions(lat=37.88, lng=-122.23, map_type="roadmap", zoom=10)
plot = gmap(google_api_key=API_KEY, map_options=map_options)
source = ColumnDataSource( data = dict(
y=[ 37.762260 ],
x=[-121.96226],
ym01=[37.762290 ],
xm01=[-121.96189 ]
))
plot.segment(x0="x", y0="y", x1="xm01", y1="ym01",line_color="green", line_width=10, source=source)
show(plot)
And can confirm that the segment does not show up. Slightly changing to show circles does work, so I have to conclude that this is a bug of some sort. Please file a detailed GitHub issue to report this bug.

How to update holoviews Bars using an ipywidgets SelectionRangeSlider?

I want to select data from some pandas DataFrame in a Jupyter-notebook through a SelectionRangeSlider and plot the filtered data using holoviews bar chart.
Consider the following example:
import numpy as np
import pandas as pd
import datetime
import holoviews as hv
hv.extension('bokeh')
import ipywidgets as widgets
start = int(datetime.datetime(2017,1,1).strftime("%s"))
end = int(datetime.datetime(2017,12,31).strftime("%s"))
size = 100
rints = np.random.randint(start, end + 1, size = size)
df = pd.DataFrame(rints, columns = ['zeit'])
df["bytes"] = np.random.randint(5,20,size=size)
df['who']= np.random.choice(['John', 'Paul', 'George', 'Ringo'], len(df))
df["zeit"] = pd.to_datetime(df["zeit"], unit='s')
df.zeit = df.zeit.dt.date
df.sort_values('zeit', inplace = True)
df = df.reset_index(drop=True)
df.head(2)
This gives the test DataFrame df:
Let's group the data:
data = pd.DataFrame(df.groupby('who')['bytes'].sum())
data.reset_index(level=0, inplace=True)
data.sort_values(by="bytes", inplace=True)
data.head(2)
Now, create the SelectionRangeSlider that is to be used to filter and update the barchart.
%%opts Bars [width=800 height=400 tools=['hover']]
def view2(v):
x = df[(df.zeit > r2.value[0].date()) & (df.zeit < r2.value[1].date())]
data = pd.DataFrame(x.groupby('who')['bytes'].sum())
data.sort_values(by="bytes", inplace=True)
data.reset_index(inplace=True)
display(hv.Bars(data, kdims=['who'], vdims=['bytes']))
r2 = widgets.SelectionRangeSlider(options = options, index = index, description = 'Test')
widgets.interactive(view2, v=r2)
(I have already created an issue on github for the slider not displaying the label correctly, https://github.com/jupyter-widgets/ipywidgets/issues/1759)
Problems that persist:
the image width and size collapse to default after first update (is there a way to give %%opts as argument to hv.Bars?)
the y-Scale should remain constant (i.e. from 0 to 150 for all updates)
is there any optimization possible concerning speed of updates?
Thanks for any help.
Figured out how to do it using bokeh: https://github.com/bokeh/bokeh/issues/7082

Resources