question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't change type of figure.x_range dynamically

See original GitHub issue

ALL 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: image

Categorical column: image

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:15 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
JulianVaicommented, Jun 20, 2019

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.

1reaction
dennismdunncommented, May 11, 2020

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.

Read more comments on GitHub >

github_iconTop 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 >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found