title: How to update a source in a JavaScript Callback of Bokeh in Python?
body: <p>I am adapting <a href="https://stackoverflow.com/q/38486119">this answer</a> for my case, where I want an interactive, standalone graph where the slider selects which column of the data to plot in a bar chart. (Standalone is crucial, I cannot run a Bokeh server, thus the need for <a href="https://bokeh.pydata.org/en/latest/docs/user_guide/interaction/callbacks.html" rel="nofollow noreferrer">JavaScript callbacks</a>.)</p>
  
  <p>The data is a rectangle of floats with 100 rows in each of the 38 columns, which all have string labels like <code>'40'</code> etc. (This is how pandas <code>.read_csv()</code> handles numerics in the header by default.) Here is a sample from the top left corner (3x3, plus the row and column labels):</p>
  
  <pre><code>        # ,        40,        41,        42,
     1.00000,   1.00000,   0.99287,   0.98489,
     2.00000,   1.00000,   0.99348,   0.98626,
     3.00000,   1.00000,   0.99433,   0.98922,
  </code></pre>
  
  <p>The code below produces the graph for the first column but does not update the graph upon moving the slider.</p>
  
  <p>By poking at it, I suspect the issue is with the JavaScript code, though <a href="https://bokeh.pydata.org/en/latest/_modules/bokeh/models/sources.html#ColumnDataSource" rel="nofollow noreferrer">ColumnDataSource</a> remains a bit mysterious to me. (A more straightforward dictionary of numeric column labels to lists of the numbers in the column does not work as <code>datasource_available</code>, though corresponds to the linked answer's use case.)</p>
  
  <pre><code>datadf = pd.read_csv('male_survival_by_pctile.csv')
  datadf.set_index('# ',inplace=True)
  years = range(40,77)
  data = {}
  data_available = {}
  
  for year in years:
      data[year] = {'top':datadf[str(year)],'x':range(1,101)}
  data_available = ColumnDataSource.from_df(datadf)
  
  from bokeh.core.properties import field
  from bokeh.io import curdoc, output_notebook, show
  from bokeh.layouts import layout, column
  from bokeh.models import (ColumnDataSource, HoverTool, SingleIntervalTicker,
                            Slider, Button, Label, CustomJS)
  from bokeh.plotting import figure
  
  output_notebook()
  
  source_visible = ColumnDataSource(data=dict(x=range(1,101),top=data_available[str(years[0])]))
  source_available = ColumnDataSource(data=data_available)
  
  plot = figure(output_backend="webgl")
  plot.xaxis.ticker = SingleIntervalTicker(interval=.01)
  plot.xaxis.axis_label = "Income percentile"
  plot.yaxis.ticker = SingleIntervalTicker(interval=.05)
  plot.yaxis.axis_label = "Survival rate"
  
  label = Label(x=1.1, y=18, text=str(years[0]), text_font_size='70pt', text_color='#eeeeee')
  plot.add_layout(label)
  
  plot.vbar(top='top',x='x',width=1,source=source_visible)
  
  slider = Slider(start=years[0], end=years[-1], value=years[0], step=1, title="Age")
  
  slider.callback = CustomJS(
      args=dict(source_visible=source_visible,
                source_available=source_available), code="""
          var selected_function = cb_obj.get('value').toString();
          // Get the data from the data sources
          var data_visible = source_visible.get('data');
          var data_available = source_available.get('data');
          // Change bar height to the selected value
          data_visible.top = data_available[selected_function];
          // Update the plot
          source_visible.trigger('change');
      """)
  
  layout = column(slider, plot)
  
  show(layout)
  </code></pre>