serv-inc
serv-inc

Reputation: 38207

Bokeh heatmap from Pandas confusion matrix

How can a Pandas DataFrame be shown as a Bokeh heatmap?

https://docs.bokeh.org/en/latest/docs/user_guide/categorical.html#heat-maps shows some example, but trying to modify always only gave an empty plot.

Example confusion matrix:

df = pd.DataFrame([[10, 0, 1], [1, 10, 0], [1, 1, 9]], 
                  columns=['A', 'B', 'C'], 
                  index=['A', 'B', 'C'])
df.index.name = 'Treatment'
df.columns.name = 'Prediction'

Upvotes: 4

Views: 6244

Answers (1)

Thomas
Thomas

Reputation: 1219

First import packages and prepare data.frame :

import pandas as pd

from bokeh.io import output_file, show
from bokeh.models import BasicTicker, ColorBar, LinearColorMapper, ColumnDataSource, PrintfTickFormatter
from bokeh.plotting import figure
from bokeh.transform import transform

df = pd.DataFrame(
    [[10, 0, 1], [1, 10, 0], [1, 1, 9]],
    columns=['A', 'B', 'C'],
    index=['A', 'B', 'C'])
df.index.name = 'Treatment'
df.columns.name = 'Prediction'

To use my solution you have to stack the data.frame :

# Prepare data.frame in the right format
df = df.stack().rename("value").reset_index()

Now, we can create the plot :

# here the plot :
output_file("myPlot.html")

# You can use your own palette here
colors = ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641']

# Had a specific mapper to map color with value
mapper = LinearColorMapper(
    palette=colors, low=df.value.min(), high=df.value.max())
# Define a figure
p = figure(
    plot_width=800,
    plot_height=300,
    title="My plot",
    x_range=list(df.Treatment.drop_duplicates()),
    y_range=list(df.Prediction.drop_duplicates()),
    toolbar_location=None,
    tools="",
    x_axis_location="above")
# Create rectangle for heatmap
p.rect(
    x="Treatment",
    y="Prediction",
    width=1,
    height=1,
    source=ColumnDataSource(df),
    line_color=None,
    fill_color=transform('value', mapper))
# Add legend
color_bar = ColorBar(
    color_mapper=mapper,
    location=(0, 0),
    ticker=BasicTicker(desired_num_ticks=len(colors)))

p.add_layout(color_bar, 'right')

show(p)

*Note : I use a more complete solution than just call HeatMap from the bokeh library because 1) you have more control on parameters like this, 2) there are lot of incompatibilities with Bokeh, Pandas, etc and this is the only solution working with my configuration.

Upvotes: 14

Related Questions