Bokeh Line log axis - bokeh

II am using bokeh and would like to have logaritmic xaxis using Line of bokeh.charts.
But impiossible.
It is possible with basic glyphs and figure (bokeh.plotting) but not for Chart.
any idea?
Or did I miss something?
Here is the code :
import bokeh.models
import bokeh.plotting
import pandas as pd</br>
from bokeh.plotting import figure, show, output_file
from bokeh.layouts import column, row
from bokeh.charts import Line
plot=Line(df,x='x',y='y',x_axis_type='log')
output_file("cycling.html",title="cycling TOP")
layout=row(plot)
show(layout)
And here is the log:
AttributeError: unexpected attribute 'x_axis_type' to Chart, similar attributes are x_mapper_type
Thks.
David

Here there is an example using Line from bokeh.charts to create a line with the x axis in logarithmic scale:
import pandas as pd
from bokeh.plotting import show, output_file
from bokeh.layouts import row
from bokeh.charts import Line
import numpy as np
x = np.logspace(0,2,100)
d = {'x': x, 'y': 1/(20**2+x**2)**0.5}
df = pd.DataFrame(data=d)
plot=Line(df,x = 'x',y='y',x_mapper_type='log')
output_file("cycling.html",title="cycling TOP")
layout=row(plot)
show(layout)
Output:

Related

Reverse range colorscale plotly

I was wondering if it is possible to make my colorscale bar ascending (from 1 to 4) instead of descending (from 4 to 1). Does anyone have clue? The picture of my current bar is underneath the code.
import pandas as pd
import plotly.graph_objects as go
fig = go.Figure(go.Densitymapbox(lat=df_dropped.latitude, lon=df_dropped.longitude, z=df_dropped.propextent,
radius=10))
fig.update_layout(mapbox_style="stamen-terrain", mapbox_center_lon=180)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
Just add reversescale=True as below:
import pandas as pd
import plotly.graph_objects as go
fig = go.Figure(go.Densitymapbox(lat=df_dropped.latitude,
lon=df_dropped.longitude, z=df_dropped.propextent,radius=10,reversescale=True
))
fig.update_layout(mapbox_style="stamen-terrain", mapbox_center_lon=180)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
For more details, please visit the reversescale section in the documentation

Simple way to place a label at the top corner of bokeh streaming plots as a python oscilloscope

I want to place a label at the top left corner of each streaming plot, be it one plot, or two plots, etc. The plots are stretched in both directions. For now, I have to manually specify a y postion depending on how many plots are shown. (y=200 for two plots, and y=440 for one plot) One may resolve it by recording the total range of y values shown in the plot, but it feels too hacky. I'm wondering if there is a simple way to do this. Thanks for any help.
from bokeh.server.server import Server
from bokeh.models import ColumnDataSource, Label
from bokeh.plotting import figure
from bokeh.layouts import column
import numpy as np
import datetime as dt
from functools import partial
import time
def f_random():
data = np.random.rand()
data = (dt.datetime.now(), data)
return data
def f_sinewave():
data = np.sin(time.time()/1.)
data = (dt.datetime.now(), data)
return data
def make_document(doc, functions, labels):
def update():
for index, func in enumerate(functions):
data = func()
sources[index].stream(new_data=dict(time=[data[0]], data=[data[1]]), rollover=1000)
annotations[index].text = f'{data[1]: .3f}'
sources = [ColumnDataSource(dict(time=[], data=[])) for _ in range(len(functions))]
figs = []
annotations = []
for i in range(len(functions)):
figs.append(figure(x_axis_type='datetime', plot_width=800, plot_height=400, y_axis_label=labels[i]))
figs[i].line(x='time', y='data', source=sources[i])
annotations.append(Label(x=10, y=200, text='', text_font_size='20px', text_color='black',
x_units='screen', y_units='screen', background_fill_color='white'))
figs[i].add_layout(annotations[i])
doc.add_root(column([fig for fig in figs], sizing_mode='stretch_both'))
doc.add_periodic_callback(callback=update, period_milliseconds=100)
if __name__ == '__main__':
# list of functions and labels to feed into the scope
functions = [f_random, f_sinewave]
labels = ['random', 'sinewave']
server = Server({'/': partial(make_document, functions=functions, labels=labels)})
server.start()
server.io_loop.add_callback(server.show, "/")
try:
server.io_loop.start()
except KeyboardInterrupt:
print('keyboard interruption')
For now you could do:
Label(x=10, y=figs[i].plot_height-30, ...)
It seems like allowing negative values to implicitly position against the "opposite" side would be a nice feature (and a good first task for new contributors), so I would encourage you to file a GitHub issue about it.

Bokeh source change

I am trying to update the data source for a Bokeh scatter plot using a function.
But instead of plotting only the new data, the plot shows all of it.
I think I'm passing a new data source to the plot, but the old plotted points persist.
How would you update the scatterplot with just new data?
Also, is there any way of retrieving the current selection in the dropdown menu without interacting with it? (i.e. without a callback that uses on_change)
import numpy as np
import pandas as pd
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Tabs, Select
from bokeh.layouts import column, row, Spacer
from bokeh.io import curdoc
from bokeh.plotting import figure, curdoc, show
#Plotting points on initial chart.
df_AB = pd.DataFrame(np.random.randint(0,100,size=(500, 2)), columns=list('AB'), index=[str(i) for i in range(1,500+1)])
pointchart=figure(plot_width=800, plot_height=700, tools=['lasso_select','box_select'],title="Point scatter")
pointchart_source= ColumnDataSource(df_AB[["A","B"]])
pointchart_glyph= pointchart.circle("A","B",source=pointchart_source)
#Dropdown
selectoroptions=['','new selection', 'other selection']
Xselector = Select(title="Dropdown:", value="", options=selectoroptions)
#Callback to update data source
def Xdropdownchange(attrname, old, new):
pointchart_glyph= pointchart.circle("X","Y",source=make_updated_source())
Xselector.on_change("value", Xdropdownchange)
#Making new/updated data source based on dropdowns.
df_XY = pd.DataFrame(np.random.randint(0,100,size=(500, 2)), columns=list('XY'), index=[str(i) for i in range(1,500+1)])
def make_updated_source():
new_x=pd.Series(list(df_XY.iloc[0:100]["X"]),name="X")
new_y=pd.Series(list(df_XY.iloc[0:100]["Y"]),name="Y")
sourcedf=pd.DataFrame([new_x,new_y]).T
pointchart_source= ColumnDataSource(sourcedf)
return pointchart_source
#Show
layout=row(column(Xselector, Spacer(width=400, height=500)),pointchart)
curdoc().add_root(layout)
!powershell -command {'bokeh serve --show Dropdown_sourcechange.ipynb'}
I changed some things in your code and it now shows your original data if you select the empty value in your dropdown or a randomly generated dataset when you select one of the other values in the dropdown. Retrieving the current selection in the dropdown without using a callback is also possible with print(Xselector.value)
import numpy as np
import pandas as pd
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Tabs, Select
from bokeh.layouts import column, row, Spacer
from bokeh.io import curdoc
from bokeh.plotting import figure, curdoc, show
#Plotting points on initial chart.
df_AB = pd.DataFrame(np.random.randint(0,100,size=(500, 2)), columns=list('XY'), index=[str(i) for i in range(1,500+1)])
pointchart=figure(plot_width=800, plot_height=700, tools=['lasso_select','box_select','wheel_zoom'],title="Point scatter")
source= ColumnDataSource(df_AB[["X","Y"]])
pointchart.circle("X","Y",source=source)
#Dropdown
selectoroptions=['','new selection', 'other selection']
Xselector = Select(title="Dropdown:", value="", options=selectoroptions)
def make_updated_source(attr, old, new):
if new == '':
source.data = ColumnDataSource(df_AB[["X","Y"]]).data
else:
df_XY = pd.DataFrame(np.random.randint(0,100,size=(500, 2)), columns=list('XY'), index=[str(i) for i in range(1,500+1)])
new_x=pd.Series(list(df_XY.iloc[0:100]["X"]),name="X")
new_y=pd.Series(list(df_XY.iloc[0:100]["Y"]),name="Y")
sourcedf=pd.DataFrame([new_x,new_y]).T
source.data = ColumnDataSource(sourcedf).data
Xselector.on_change("value", make_updated_source)
#Retrieve selection in dropdown withoud on_change
print(Xselector.value)
#Show
layout=row(column(Xselector, Spacer(width=400, height=500)),pointchart)
curdoc().add_root(layout)
!powershell -command {'bokeh serve --show Dropdown_sourcechange.ipynb'}

Bokeh simple bar chart

I'm new to the method. I created the following input, but it gives me an empty output. What did I miss? Thank you.
import pandas as pd
from bokeh.charts import Bar
import pandas as pd
from bokeh.plotting import figure, output_file, show
mortality_age = pd.read_csv("mortality_by_age.csv")
x=mortality_age["Age Range"]
y=mortality_age["Deaths per 100,000 Live Births:"]
plot = figure(title="Example of a vertical bar chart")
plot.vbar(x, top=y, width=0.5,color="#CAB2D6")
output_file("vertical_bar.html", mode="inline")
show(plot)
what version of Bokeh are you using?
Using 12.10, I have managed to get a plot to show using the code below, using the example contained in the documentation.
# import pandas as pd
from bokeh.plotting import figure, output_file, show
# from bokeh.charts import Bar # I had issues with this line working
# mortality_age = pd.read_csv("mortality_by_age.csv")
# x=mortality_age["Age Range"]
# y=mortality_age["Deaths per 100,000 Live Births:"]
x=[1, 2, 3, 4, 5]
y=[6, 7, 6, 4, 5]
plot = figure(title="Example of a vertical bar chart")
plot.vbar(x=[1, 2, 3, 4, 5], top=y, width=0.5, color="#CAB2D6")
output_file("vertical_bar.html", mode="inline")
show(plot)
My recommendations would be to check the version of bokeh you are using, and then check the data contained in your csv file, it might be possible there is nothing in there.

Bokeh missing plots in IPython notebook

Maintainers note: this question is obsolete. Calling multiple glyph methods on a figure automatically combines (and has for many years). For information on modern Bokeh, see:
https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html
OBSOLETE:
I am running the Bokeh tutorial in the IPython notebook. It only displays the scatter plot and not the line plot. From the command-line it renders both plots separately.
How do I get both graphs in the same chart, on top of each other?
import numpy as np
import bokeh.plotting as bplt
bplt.output_file("bokehtest.html")
#bplt.output_notebook(url=None)
x = np.linspace(-2*np.pi, 2*np.pi, 100)
y = np.cos(x)
bplt.line(x, y, color="red")
bplt.scatter(x, y, marker="square", color="blue")
bplt.show()
OBSOLETE ANSWER: see https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html* for modern Bokeh
You just need to call bplt.hold() before any of the plotting commands, to toggle the "hold state". The following code works for me:
import numpy as np
import bokeh.plotting as bplt
bplt.output_file("bokehtest.html")
#bplt.output_notebook(url=None)
x = np.linspace(-2*np.pi, 2*np.pi, 100)
y = np.cos(x)
bplt.hold() # <--- The important line!!
bplt.line(x, y, color="red")
bplt.scatter(x, y, marker="square", color="blue")
bplt.show()
OBSOLETE ANSWER: see https://docs.bokeh.org/en/latest/docs/user_guide/plotting.html for modern Bokeh
Try using the figure command like in this example:
import numpy as np
import bokeh.plotting as bplt
bplt.output_file("bokehtest.html")
x = np.linspace(-2*np.pi, 2*np.pi, 100)
y = np.cos(x)
bplt.figure()
bplt.line(x, y, color="red")
bplt.scatter(x, y, marker="square", color="blue")
bplt.show()

Resources