Squarify w/ Bokeh for Treemap

Trying to get squarify w/ Bokeh working in Jupyter notebook. I’m guessing something deeper in bokeh w/ the canvas engine, but hoping for something obvious I’m missing.

w/ squarify plot helper and matplotlib

w/ squarify and bokeh

squarify repo | GitHub - laserson/squarify: Pure Python implementation of the squarify treemap layout algorithm

Jupyter Minimal Example

import pandas as pd
import squarify
import matplotlib.pyplot as plt
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
output_notebook()

#dict init
df = dict(
    one=[50],
    two= [25],
    three = [12],
    four = [6],
    five = [3],
    )

#df init
df = pd.DataFrame.from_dict(
    data=df, 
    orient='index',
    columns=[
        'amount',
    ])
df.index.name = 'labels'

#create a tree map
fig, ax = plt.subplots(1, figsize = (10,5))
squarify.plot(
    sizes = df.amount.values,
    label = df.index,
    )
plt.axis('off')
plt.show()

#squarify
x,y = 0,0
height = 400
width = 600

df.sort_values(by='amount', inplace=True, ascending=False)
df['rect_norm'] = squarify.normalize_sizes(df.amount, width, height)
rect_df = pd.DataFrame.from_dict(
    data=squarify.squarify(df.rect_norm, x, y, width, height) 
    )
rect_df.set_index(df.index, inplace=True)
#combine back
df = df.join(rect_df, how='left')

#create a treemap w/ bokeh
source = ColumnDataSource(df)
#define figure and glyphs
p = figure(height=height, width=width)
p.rect('x', 'y', 'dx', 'dy', source=source,
    width_units='data',
    height_units='data',
    dilate=False,
    )
show(p)

Bokeh rect coordinates are center coordinates (because Bokeh rects can be rotated about a center). Is squarify returning corner coordinates (e.g. lower-left)? If so, you would need to convert them before passing to Bokeh, since there are no Bokeh glyphs that take a corner coordinate and width/height.

For “rect” like glyphs, your options are

  • rectx, y, width, height (centered at x, y)
  • quadtop, bottom, left, right
  • vbartop, bottom, width, x (centered on x)
  • hbarleft, right, height, y (centered on y)

BTW Once you have things working, if you wanted to add a treemap.py example to the repo, we would be glad to help with a PR.

1 Like

A little center shift for the win! Thanks for the nudge.

df['x_center'] = df.x + df.dx/2
df['y_center'] = df.y + df.dy/2

I’ll try and push this simple one out there sometime soon.

1 Like

FYI I proposed a new glyph with these missing semantics:

2 Likes