Quick Reference · squarified treemap layout

squarify cheat sheet

A pure-Python layout algorithm, not a charting library. Give it values sorted largest-first and a rectangle to fill; it returns tiles whose area is proportional to value, shaped as close to squares as it can. squarify.plot() draws them in Matplotlib — or take the raw {x, y, dx, dy} dicts and render them anywhere.

import / setup values & normalize layout (the core) squarify.plot labels & text colour & style gotcha most common

Distilled & cross-checked against the squarify source of truth: github.com/laserson/squarify (README + __init__.py API docs) · PyPI · python-charts.com · python-graph-gallery.com · algorithm: Bruls, Huizing & van Wijk, "Squarified Treemaps" (2000)

Values in, rectangles out — and the two ways to use them
THE FOUR STEPS 1 · Sort descending values.sort(reverse=True) positive values only 2 · Normalize normalize_sizes(v, dx, dy) sum(sizes) == dx * dy 3 · Lay out squarify(sizes, x, y, dx, dy) area ∝ value, near-square 4 · Rectangles list of {x, y, dx, dy} plain dicts, input order TWO WAYS TO USE IT — plot() DOES STEPS 1–4 PLUS THE DRAWING squarify.plot(sizes, ...) the one-call convenience normalizes + lays out + draws bars & labels → returns a Matplotlib Axes normalize_sizes() + squarify() the raw layout no Matplotlib needed — pure Python → draw with d3.js · SVG · anything padded_squarify() is the same layout with a small fixed gap around every tile, so borders stay visible.
Both paths, side by side
import squarifyimport matplotlib.pyplot as pltvalues = [500, 433, 78, 25, 25, 7]values.sort(reverse=True) # REQUIRED: largest first# --- path A: one call draws it -------------------------------squarify.plot(sizes=values, label=["A","B","C","D","E","F"], pad=True, alpha=.8, ec="white") # ec → bar edgecolorplt.axis("off") # a treemap has no axes# --- path B: raw rectangles, render anywhere -----------------norm = squarify.normalize_sizes(values, 700, 433) # sum → 700*433rects = squarify.squarify(norm, 0, 0, 700, 433) # x, y, dx, dy# [{'x': 0.0, 'y': 0.0, 'dx': 327.7, 'dy': 433.0}, ...]
01Setup & Importonce per project
02The Whole APIfour functions
03squarify.plot()the one-call path
04Preparing Your Valuesthe two rules
05normalize_sizes()values → area
06squarify() & padded_squarify()the algorithm
07The Rectangle Dictwhat you get back
08Labels & Value Textannotate tiles
09Colourthe palette
10Borders & Bar kwargstile styling
11Figure, Axes & Savingit's Matplotlib
12With pandasreal data in
13Recipescopy & adapt
14Limits & Alternativesknow the edges

Four ideas that explain the layout

The rule the whole package rests on, why "squarified" matters, the shape of what comes back, and the two ways to use it. The treemaps below are the algorithm's real output for the README's values [500, 433, 78, 25, 25, 7].

area ∝ value

Every tile's area — not its width or height — encodes the value. This is the algorithm's actual output.

500 433 78 25 25 7 sum(values) is mapped onto the full canvas area

why "squarified"?

Naive slice-and-dice makes unreadable slivers. Squarify keeps every tile's aspect ratio as close to 1 as it can.

slice-and-dice slivers → hard to compare squarified near-squares → readable same six values, both layouts

the rectangle it returns

Each tile is a plain dict: an origin corner plus a width and a height. Nothing framework-specific.

(x, y) dx dy area ∝ value { "x":0.0, "y":0.0, "dx":327.7, "dy":433.0 }

plot() vs raw rectangles

One call draws a Matplotlib treemap; the layout functions hand back geometry you can render in anything.

squarify.plot(...) a finished Matplotlib Axes squarify(...) [{ x:0.0, y:0.0, dx:327.7, dy:433.0 }, ... ] geometry for d3 · SVG · anything same algorithm underneath

Worth memorizing

sort descending yourselfsquarify never sorts — unsorted input silently lays out badly
positive values onlyan area can't be zero or negative
sum(sizes) == dx * dywhat normalize_sizes guarantees before layout
plot() normalizes for youonly the raw path needs normalize_sizes
pad is a booleannot a gap size — pad=0.25 and pad=True are identical
default colours are randompass color= or every run looks different
plot() returns Axesa single Axes, not a (fig, ax) tuple
plt.axis("off")treemap axes carry no meaning
output order == input orderso rects[i] lines up with values[i] and your labels
ec= and linewidth=loose kwargs merge into bar_kwargsAxes.bar
flat, not hierarchicalrecurse into a tile's rect, or use plotly.express.treemap
layout needs no matplotlibpure Python → JSON → render in the browser