Can't change type of figure.x_range dynamically
See original GitHub issueALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)
$ bokeh info
Python version : 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
IPython version : 7.1.1
Tornado version : 5.1.1
Bokeh version : 1.0.1
BokehJS static path : /path/to/my/python3.7/site-packages/bokeh/server/static
node.js version : v9.7.1
npm version : 5.6.0
Description of expected behavior and the observed behavior
I am trying to implement a plot where the user can select a column from a dropdown and see the histogram of values in the column. Some columns may be categorical, and some are continuous, so I’ve using a vbar
and setting the width accordingly. However, this means that I sometimes need a DataRange1d
, and sometimes a FactorRange
. Changing my figure’s x_range
to a FactorRange
causes my plot to be reset and not show any output. There is no error, the glyphs just disappear.
Complete, minimal, self-contained example code that reproduces the issue
This is about as minimal as I could get it, sorry.
from bokeh.plotting import Figure, ColumnDataSource
from bokeh.models.widgets import Dropdown
from bokeh.models.ranges import DataRange1d, FactorRange
from bokeh.layouts import row
from bokeh.io import curdoc
import pandas as pd
import numpy as np
def _col_stats(col,):
"""Value counts or histogram of column"""
is_str = isinstance(col.values[0], str)
if is_str:
counts = col.value_counts().sort_index()
hist = counts.values
edges = np.array(counts.index)
else:
hist, edges = np.histogram(col, bins="auto")
return hist, edges
def _hist_source_dict(hist, edges):
if isinstance(edges[0], str):
return {"top": hist, "x": edges, "width": 0.8 * np.ones_like(edges)}
else:
w = np.diff(edges)
x = np.array(edges[:-1]) + w / 2
return {"top": hist, "x": x, "width": w}
def _update_histogram(figure, source, hist, edges, name=""):
"""Why doesn't this work?"""
if isinstance(edges[0], str):
figure.x_range = FactorRange(factors=edges)
else:
figure.x_range = DataRange1d()
source.data = _hist_source_dict(hist, edges)
if name:
figure.title.text = name
df = pd.DataFrame(
{"a": [1, 2, 3, 4, 3, 1, 2, 3, 4, 1], "b": list("abcdcbaeda")}
)
columns = df.columns
# initial values
first_col = columns[0]
first_hist, first_edges = _col_stats(df[first_col])
# set up data sources
hist_source = ColumnDataSource(data=_hist_source_dict(first_hist, first_edges))
# set up dashboard components
plot = Figure(
title=first_col,
tools="xpan,xwheel_zoom,box_zoom,reset",
active_drag="xpan",
active_scroll="xwheel_zoom",
)
plot.vbar(top="top", x="x", width="width", bottom=0, source=hist_source)
dropdown = Dropdown(
label="Column", menu=[(col, col) for col in df.columns], value=first_col
)
# configure callbacks
def dropdown_callback(attr, old, new):
global df, plot, hist_source
hist, edges = _col_stats(df[new])
_update_histogram(plot, hist_source, hist, edges, new)
dropdown.on_change("value", dropdown_callback)
# Position elements in document
root = row(plot, dropdown)
curdoc().add_root(root)
If you save this and run it with bokeh serve
, selecting ‘b’ from the dropdown will blank out the plot, but there is no error.
Screenshots or screencasts of the bug in action
Continuous column:
Categorical column:
Issue Analytics
- State:
- Created 5 years ago
- Comments:15 (6 by maintainers)
Top Results From Across the Web
Unable to update figure when new data are passed ("dynamic ...
After multiple attempts, I found this working combination of instructions: Add %matplotlib notebook at the beginning of the code to allow ...
Read more >Update dynamically created figure y-axis based on ...
i have a very simple layout: app.layout = dbc.Container([dbc.Tabs([dbc.Tab(label='Tab1', tab_id='tab1'), dbc.
Read more >Dynamic plotting with matplotlib « BRG blog
Matplotlib is a great tool to visualise two-dimensional geometric data (and 3D data to some extent). You can also use it to dynamically...
Read more >Use defined names to automatically update a chart range
... new information to an existing chart range in Microsoft Excel, create defined names that dynamically change as you add or remove data....
Read more >Specify Axis Limits - MATLAB & Simulink - MathWorks
Figure contains an axes object. The axes object contains an object of type surface. Revert Back to Default Limits. Create a mesh plot...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Not quite shure if the issue has been solved, but a way to get around is by overwriting the factor attribute of the figure.x_renge object. so for your particular case will look something like :
figure.x_range.factors = edges
This on the docs is not completely clear and its necessary an example that covers this figure() related modifications made dynamically, i’ll be glad to share an example of this.
I’ve been attempting to update fig{x,y}_range.{start,end} in a callback function in a mapping application, to show different state maps in the correct aspect ratio. I update the data source for the figure, then directly update the x_range.start, etc. Running this under my bokeh server (2.0.1) this works, but randomly fails. Sometimes all limits are refreshed and the map displays properly. Other times, one or more limit fails to update, leading to a distorted map or no visible rendering of the state. This may be related to the problem reported by @mattpap above. It appears to be unresolved.