Here’s a modification of that same heatmap that filters based on year, which has the effect of column-highlighting you describe.
import pandas as pd
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import (BasicTicker, ColorBar, ColumnDataSource,
CustomJS, LinearColorMapper,
PrintfTickFormatter, Select)
from bokeh.plotting import figure
from bokeh.sampledata.unemployment1948 import data
from bokeh.transform import transform
data.Year = data.Year.astype(str)
data = data.set_index('Year')
data.drop('Annual', axis=1, inplace=True)
data.columns.name = 'Month'
# reshape to 1D array or rates with a month and year for each row.
df = pd.DataFrame(data.stack(), columns=['rate']).reset_index()
source = ColumnDataSource(df)
# this is the colormap from the original NYTimes plot
colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
mapper = LinearColorMapper(palette=colors, low=df.rate.min(), high=df.rate.max())
p = figure(plot_width=800, plot_height=300, title="US unemployment 1948—2016",
x_range=list(data.index), y_range=list(reversed(data.columns)),
toolbar_location=None, tools='', x_axis_location="above")
p.rect(x="Year", y="Month", width=1, height=1, source=source,
line_color=None, fill_color=transform('rate', mapper))
color_bar = ColorBar(color_mapper=mapper,
ticker=BasicTicker(desired_num_ticks=len(colors)),
formatter=PrintfTickFormatter(format="%d%%"))
p.add_layout(color_bar, 'right')
year_filter = CustomJS(args=dict(source=source), code="""
var selected_year = cb_obj.value
// clear out previously selected values
source.selected.indices = []
// add every row (square) that matches the year from the Select to our source.selected.indices
source.data.Year.forEach((source_year, i) => {
console.log(`selected year is ${selected_year} and source year is ${source_year} and index is ${i}`)
if (source_year == parseInt(selected_year)) {
console.log("match!")
source.selected.indices.push(i)
}
});
// update the plot
source.change.emit()
""")
p.axis.axis_line_color = None
p.axis.major_tick_line_color = None
p.axis.major_label_text_font_size = "7px"
p.axis.major_label_standoff = 0
p.xaxis.major_label_orientation = 1.0
year_select = Select(options=df.Year.unique().tolist())
year_select.js_on_change("value", year_filter)
col = column(children=[p, year_select])
show(col)
Try it out and let me know if you have any questions about what’s going on in the code. One thing I did not include was a “resetter” option in the drop-down, to go back to a state where no particular column is selected, but that would be a nice add.