
Chris Parmer
October 24, 2026
Treemaps - A Complete Guide
TL;DR
- A treemap draws a hierarchy as nested rectangles, with each rectangle's area proportional to its value, so hundreds of parts of a whole fit on one screen.
- Treemaps are also known as tree maps and tree-maps, and are similar to sunburst charts and icicle charts.
- Use one for positive values that add up (budgets, market caps, disk usage, sales by region and product) when the question is what's big and where it sits.
- Use a sorted bar chart instead for fewer than about ten items or close values, and a line chart for anything over time.
- Any coding agent can make one with Plotly in a minute. In Python it's px.treemap(df, path=[...], values=...).
What is a treemap?
Treemaps look like this:

Data: SEC filings (shares), Yahoo Finance (prices) and datasets/s-and-p-500-companies (sectors).
How do you read a treemap? In the example above, notice these things:
- Each rectangle is one company, and its area is its market value. Nvidia, Apple and Alphabet get the biggest tiles because they are the three biggest companies, and you can see that without reading a single number.
- Every company sits inside the block for its sector, so the chart compares sectors too. Information technology is the largest block, with about a third of the total value.
- Color carries a second number on top of size, here the 2025 price return. Bright green tiles rose, red tiles fell, and the dark ones barely moved, so a big red tile like UnitedHealth stands out right away.
- Inside each block the largest tiles start in the top left and get smaller toward the bottom right, which makes it easy to find the leaders of each sector.
- The smallest companies get tiles too small to label. A treemap shows how the whole is split up, and you hover over a tile to see the details.
It's often used for charts like these:

A budget. Four agencies made 76% of the $7.78 trillion of fiscal 2025 federal outlays drawn here, and interest on the debt ($974B) was more than all of Defense's military programs. Data: US Treasury, Monthly Treasury Statement, September 2025.

A map sized by what countries produce instead of their land. The 52 African economies with 2024 data add up to $2.9 trillion of GDP, less than France alone ($3.2 trillion). Data: World Bank, World Development Indicators.

Files on a disk. 48% of the 40.4 MB plotly Python package is four JavaScript bundles that each contain plotly.js. Data: the plotly 7.1.0 wheel on PyPI.
A short history
Ben Shneiderman invented the treemap around 1990 at the University of Maryland, to see what was filling his lab's 80-megabyte hard disk shared by 14 users, and published it in 1992 in ACM Transactions on Graphics. His layout, slice-and-dice, splits each folder in the opposite direction from its parent, which keeps the order but makes long thin strips:

In 2000, Bruls, Huizing and van Wijk published the squarified layout, which keeps tiles close to square and is Plotly's default. Martin Wattenberg's Map of the Market for SmartMoney.com (1998) made the stock market map at the top of this page a standard view.
Alternatives to a treemap
Here's the same household budget drawn six ways. Some are better for the question, some worse, some just different:

- Sorted bar chart (better for precise comparisons). People judge length on a shared baseline more accurately than area, as Cleveland and McGill (1984) measured, so use bars for fewer than about ten items or when close values matter. You lose the nesting.
- Sunburst (different). Each level is a ring, which shows the depth of the tree better but makes sizes harder to compare. See our sunburst chart guide.
- Icicle (different). The sunburst unrolled into columns, the layout of flame graphs for CPU profiles, where small items become slivers. See our icicle chart guide.
- Pie chart (works too, for one level). Good for parts of a whole, especially sorted largest first, which Plotly's pie charts do by default. Here housing is 32.9% of spending. Past about ten slices the small ones get hard to label.
- Sankey diagram (different). Shows the same split as flows from the total to groups to items, and also handles flows between stages that aren't a strict hierarchy. See our Sankey diagram guide.
Here's where the bar chart wins. Food at $9,986 and insurance and pensions at $9,557 look the same as tiles, while the bars show the 4.5% gap:

How to make a treemap
With AI
ChatGPT, Claude Code, GitHub Copilot, Cursor and other AI tools are excellent at writing Plotly code. Name Plotly in the prompt, describe the hierarchy and what size and color mean, and list the checks you want:
Make a plotly treemap from spend.csv (columns: team, service, resource, monthly_cost_usd).- Hierarchy: team -> service -> resource. Size = monthly_cost_usd.- Within each service keep the 10 biggest resources and fold the rest into "Other <service>" in gray.- One color per team; children use their team's color.- Tile text: bold name, $ value and % of total. Hide text that doesn't fit (uniformtext minsize 10).- Don't draw a root tile or the pathbar. White lines between tiles.- A title that states the main takeaway.- Assert that every parent equals the sum of its children.- Save it as treemap.html and as a PNG at 2x scale.
With Plotly Studio
Plotly Studio is a desktop app where you point an AI at a dataset and it builds charts and a Dash app around your questions. Ask for a treemap the same way:
Show a treemap of S&P 500 companies grouped by sector, sized by market cap and colored by return this year on a red to green scale centered on zero. Add a dropdown to switch the color between 1-day, 1-month and year-to-date return.
Make a treemap chart in Python or JavaScript
This is the code AI tools write under the hood. In Python, Plotly Express builds the hierarchy from a flat table with one column per level:
import plotly.express as pxdf = px.data.gapminder().query("year == 2007")fig = px.treemap(df,path=[px.Constant("World"), "continent", "country"],values="pop",color="lifeExp",color_continuous_scale="RdBu",color_continuous_midpoint=df["lifeExp"].mean(),)fig.update_traces(root_color="#ffffff", texttemplate="<b>%{label}</b><br>%{value:,.0f}")fig.show()
In JavaScript, plotly.js takes one entry per tile with its label, its parent and its value:
<div id="chart"></div><script src="https://cdn.plot.ly/plotly-4.1.1.min.js"></script><script>Plotly.newPlot("chart", [{type: "treemap",labels: ["Essentials", "Housing", "Food", "Lifestyle", "Entertainment"],parents: ["", "Essentials", "Essentials", "", "Lifestyle"],values: [35421, 25435, 9986, 3635, 3635],branchvalues: "total",texttemplate: "<b>%{label}</b><br>$%{value:,}"}]);</script>
With branchvalues="total", each parent's value must equal the sum of its children, or Plotly draws an empty chart without an error.
To use the same treemap chart in React, install react-plotly.js (npm install react-plotly.js plotly.js) and pass the same data and layout to its <Plot> component.
Share it
Every Plotly chart has a Share chart button (the cloud icon in its toolbar) that uploads it to Plotly Cloud and gives you a link. Only you can see it until you change its visibility.
For a live app, put the chart in a Dash app and publish it with the Plotly Cloud CLI. Coding agents can run these commands for you:
pip install "dash[cloud]"plotly user loginplotly app publish
If your data has to stay in your own cloud or data center, publish to Dash Enterprise instead.
Dos and don'ts
Plotly's defaults are made for exploring. For a published chart, most of the work is deciding what to leave out. Here is the same household budget both ways.
Don't draw the root tile, give every tile its own color, or print raw unformatted numbers:

Do use one color per group, label the group headers, put dollar values on the tiles and hide labels that don't fit:

Use color for one other thing
Area already shows size, so color is free to say something else. Here are four options on the same data.
By group. Shows the hierarchy, and it's a good default when the groups matter.

Highlight one story. Housing is 33% of spending, so it's the only color and everything else is gray.

By size (avoid). Color repeats what area already shows, so it adds nothing.

By a second variable. Here it's the change in spending since 2019: red grew faster than the 22.6% overall increase, and blue grew slower.

Checklist
Do
- Write a title that states the takeaway.
- Put the value and share on the tiles with texttemplate, and hide labels that don't fit with uniformtext=dict(minsize=10, mode="hide").
- Separate groups with white lines and header strips (marker.pad.t).
- Fold the long tail into a gray "Other" tile in each group.
- Hide the root and the pathbar in static images.
Don't
- Color by size, because area already shows it.
- Use a rainbow of colors that mean nothing.
- Size tiles by rates, averages or percentages, which don't add up.
- Show more than two or three levels in a static chart.
Options to customize
These are the go.Treemap (and px.treemap) options that matter most. The full list is in the Plotly treemap documentation.
- path (px only): builds the tree from DataFrame columns, top level first.
- ids, labels, parents: the tree, one row per tile. Use when labels repeat under different parents.
- values: the size of each tile.
- branchvalues: total (a parent's value is the sum of its children) or remainder (added on top).
- marker.colors: one color per tile, for groups or a highlight.
- marker.colorscale, cmid, cmin, cmax: map a number to color; cmid centers a diverging scale.
- marker.pad: padding inside each parent; t makes a header strip.
- marker.line: tile borders, usually thin white lines.
- marker.cornerradius: rounded corners, 2-4 px for a softer look.
- marker.depthfade: fades parent colors so depth reads as shade.
- marker.pattern: hatching, for a second category without a second color.
- tiling.packing: squarify (default), binary, slice-dice, dice, slice or dice-slice. Slice and dice keep a strict order.
- tiling.pad: the gap between tiles.
- texttemplate: tile text with %{label}, %{value}, %{percentRoot}, %{percentParent}.
- textposition: top left reads like a file explorer.
- uniformtext (layout): a minimum font size; mode="hide" drops text that won't fit.
- maxdepth, level: how many levels to show, and which tile to start from.
- root_color, pathbar.visible: hide both in static charts.
- sort: set to False to keep your own order.
- domain: place several treemaps side by side.
More treemap examples
Eight more treemaps built from real public data, each with its source, the technique that makes it work and a prompt to rebuild it.
1. What's in the CPI basket, and what got more expensive

Weight in the basket is area and the 12-month price change is color, centered on the 3.7% rise for all items. Shelter is 35.6% of the basket and rose 3.2%, close to the overall rate, while the deep red tiles are small: motor fuel is 3.0% of the basket and rose 35%. Car insurance (-5.0%) and health insurance (-9.0%) got cheaper. Data: BLS CPI-U relative importance (December 2025) and indexes for September 2025 and September 2026, US city average.
Tip: centering the diverging scale on the 3.7% all-items rate instead of zero makes blue mean slower than overall inflation and red mean faster.
Get the data from the BLS CPI-U relative importance table (December 2025) and CPI indexes for September 2025and September 2026 (bls.gov)and shape it into a table(columns: group, item, item_code, weight in percent of the CPI-U basket at Dec 2025,index_sep2025, index_sep2026, change_12m as a fraction; BLS CPI-U, U.S. city average).Build a plotly treemap of the CPI basket: group -> item, sized by weight.- Color each item by change_12m on a diverging blue-white-red scale centered on the all-itemsrate (3.74%) and capped 8 points either side; gray where change_12m is empty.- Dark group header strips showing the group's weight; tile text "<b>item</b><br>weight% · +x.x%".- White text on dark tiles, black on light ones; uniformtext minsize 10, mode hide.- Add a horizontal colorbar labeled with the all-items rate. Title with the takeaway; cite BLS.
Another way to see it: a dot plot of weight against price change, next to a bar chart of contributions, shows that motor fuel (3.0% of the basket) added 1.04 points to inflation, more than owners' equivalent rent (26.2% of the basket, 0.86 points). The treemap is still better for seeing the whole basket at once.

2. GLP-1 drugs in Medicare Part D

Medicare Part D paid $288.7 billion for drugs in 2024 before rebates. With only the GLP-1 drugs in color, the class shows up under Novo Nordisk, Eli Lilly, AstraZeneca and Sanofi and adds up to $27.9 billion, 9.7% of the bill. Ozempic alone cost $13.0B, second only to the blood thinner Eliquis ($20.8B). Data: CMS Medicare Part D Spending by Drug, 2024 (the GLP-1 flag and company grouping are ours).
Tip: one highlight color on a gray chart picks out a class of drugs wherever it sits in the hierarchy, which a bar chart grouped by manufacturer can't do.
Get the data from CMS Medicare Part D Spending by Drug, 2024 (data.cms.gov)and shape it into a table(columns: manufacturer, drug, generic, spending_mn in US$ millions of 2024 Part D gross drugcost before rebates, beneficiaries, glp1 = True for GLP-1 receptor agonists).Build a plotly treemap: manufacturer -> drug.- Draw the 15 largest manufacturers; inside each, drugs >= $900M (and every GLP-1 drug >= $50M)get their own tile and the rest become "N other drugs". All other manufacturers = one tile.- Color GLP-1 drugs blue and everything else in grays (darker gray manufacturer headers).- Label tiles "<b>drug</b><br>$X.XB"; uniformtext minsize 10, mode hide.- Title with the GLP-1 total and share; subtitle notes gross cost before rebates and that theGLP-1 flag and company grouping are ours. Check parents = sum of children.
3. Where US jobs are growing and shrinking

Tiles are sized by US payroll jobs in September 2026 and colored by the change over 12 months. Health care and social assistance added 520,000 jobs, more than the 496,000 net gain of the whole economy, while the federal government lost 232,000 (-8.0%) and information lost 120,000 (-4.2%). Retail's 15.5 million jobs fill a big, nearly neutral tile. Data: BLS Current Employment Statistics, seasonally adjusted, September 2026 (preliminary) vs September 2025.
Tip: size is the level and color is the change, on a diverging scale with cmid=0 clipped at ±4%, so small industries with big swings stand out.
Get the data from BLS Current Employment Statistics (CES) through the BLS public API (api.bls.gov)and shape it into a table(columns: supersector, industry, ces_code, jobs_k_latest, jobs_k_year_ago, change_k, change_pct,latest_month, year_ago_month, latest_preliminary, total_nonfarm_k_latest, total_nonfarm_k_year_ago;thousands of jobs, BLS CES, seasonally adjusted).Build a plotly go.Treemap of US jobs: root "All US payroll jobs" -> supersector -> industry,branchvalues="total", sized by jobs_k_latest.- Color every tile by its 12-month percent change on a red-gray-blue diverging scale with cmid=0,clipped at +/-4%, with a slim horizontal colorbar titled "12-month change".- Leaves show name, jobs (15.5M) and change (+26k, +0.2%); white text on the saturated tiles.Supersector totals go in the header label (marker.pad.t ~24).- Title with the takeaway (health care and social assistance vs the total gain); note "preliminary".- Assert that each supersector equals the sum of its industries.
4. The weight of all life on Earth

All life on Earth weighs about 550 billion tonnes of carbon and plants are 82% of it, so animals (2.48 Gt C, 0.45%) would be a speck. A second panel enlarges the animal tile, where livestock (0.107 Gt C) and humans (0.055 Gt C) outweigh all wild mammals (0.007 Gt C), humans by about 7.5 to 1. Some of these estimates carry 10-fold or larger uncertainty. Data: Bar-On, Phillips and Milo, "The biomass distribution on Earth", PNAS 2018 (doi:10.1073/pnas.1711842115).
Tip: two go.Treemap traces placed with domain, the second re-rooted on the animals and joined to the first by add_shape zoom lines, show a value thousands of times smaller than the total instead of letting it disappear.
Get the data from Bar-On, Phillips & Milo, PNAS 2018 (github.com/milo-lab/biomass_distribution)and shape it into a table(columns: kingdom, group, subgroup, gt_c, uncertainty_fold; gt_c = gigatonnes of carbon,the best estimates of Bar-On, Phillips & Milo, PNAS 2018).Build a plotly figure with two treemaps side by side using `domain`.- Left (x 0-0.47): one tile per kingdom (sum gt_c by kingdom). Plants green, animals orange,everything else in grays. Label each tile with its Gt C and share of the total.- Right (x 0.55-1): only the animals, as group -> subgroup (arthropods and mammals havesubgroups). Pale orange tiles, with humans, livestock and wild mammals in strong colors.- Draw an outline around the animals tile on the left and two lines from it to the cornersof the right panel, so it reads as a zoom. Compute the tile position by reproducingd3's squarify layout, or place it by eye and check.- Title with the takeaway and say in a note that the values are estimates with large uncertainty.- Check that each kingdom equals the sum of its rows and the total is about 549 Gt C.
Another way to see it: a log-scale bar chart shows the full range precisely, from plants (450 Gt C) to wild birds (0.0017 Gt C), but loses the sense of how small animals are next to plants.

5. The world's electricity mix

The world generated 30,912 TWh of electricity in 2024, split here by country and then by source, with each source keeping one color everywhere. China's coal tile (5,828 TWh, 58% of China's power) is bigger than the entire United States (4,391 TWh), France is mostly nuclear (68%) and Brazil mostly hydro (55%). Data: Ember, Yearly Electricity Data, 2024.
Tip: leaf colors are set by source in marker.colors, and the legend comes from invisible go.Scatter traces because treemaps have no legend of their own.
Get the data from Ember's Yearly Electricity Data (ember-energy.org), 2024and shape it into a table(columns: country, source, twh; electricity generation in 2024 in TWh for the 12 largestgenerators plus "Rest of world"; Ember Yearly Electricity Data).Build a plotly treemap country -> source.- Give every source one fixed color, the same under every country: coal #3d3c39, gas #8a8983,other fossil #c3c2bc, nuclear #6250d6, hydro #2a78d6, wind #1baf7a, solar #eda100,bioenergy #008300, other renewables #e87ba4. Country tiles are white with a bold headerthat includes the country total.- Add a horizontal legend above the plot using one invisible go.Scatter trace per source(square markers), with each source's share of world generation in its name.- Label large leaves with source, TWh and share of the country; hide labels on tiny tiles.- Title: China's coal plants alone generated more electricity than the entire US.- Check that the table adds up to about 30,912 TWh.
Another way to see it: a 100% stacked bar per country compares mixes on one baseline, showing fossil fuels at 98% of Saudi Arabia's electricity and 5% of France's. Every bar has the same length, though, so China's coal no longer looks as big as it is.

6. Every described species, down to the beetles

The Catalogue of Life lists 2,086,650 described living species, and animals are 1,490,279 of them. Insects alone are 1,012,723, almost half of everything described, and beetles (332,013 species) are the largest single tile, 4.4 times all vertebrates together (76,070). Mammals are just 6,368 species. Data: Catalogue of Life (COL26.10, October 2026) via the ChecklistBank API; viruses are excluded.
Tip: maxdepth=4 limits the levels in the static image while the interactive version keeps the whole tree for readers to click into.
Get the data from the Catalogue of Life (COL26.10) through the ChecklistBank API (checklistbank.org)and shape it into a table(columns: kingdom, phylum, class, order, species; number of described living species,Catalogue of Life COL26.10; deeper columns are blank where the tree stops).Build a plotly treemap kingdom -> phylum -> class -> order with maxdepth=4.- Build ids from the path and skip blank levels, so leaves can sit at any depth.- Fold small branches into "Other ..." tiles (phyla under 8,000, classes under 6,000,insect orders under 20,000).- Color for one comparison: beetles (Coleoptera) dark orange, other insect orders mid orange,vertebrate classes blue, all other tiles a pale tint of their kingdom's color.- Add common names (Coleoptera -> Beetles, Teleostei -> Bony fishes) and label only tilesbig enough to read.- Title with the computed numbers: insects' share of animal species and beetles vs vertebrates.- Check that every parent equals the sum of its children.
Another way to see it: an icicle chart lays the tree out in columns, which shows where it stops early and where it goes four levels deep, but the 76,070 vertebrates shrink to thin lines that need labels outside the chart.

7. Python's most downloaded packages

Over the 30 days to October 1, 2026, the top 150 PyPI packages were downloaded 70.9 billion times, and HTTP and networking libraries took 21.0% of that. boto3 leads with 2.46 billion, and the data and science libraries add up to 5.8%. Downloads include CI runs and mirrors. Data: hugovk/top-pypi-packages, 30 days to October 1, 2026 (grouping is ours).
Tip: in each category, packages under 0.4% of the total fold into one lighter "+N more" tile, kept last with sort=False, so the chart stays readable without dropping any downloads.
Get the data from hugovk's top PyPI packages list (hugovk.github.io/top-pypi-packages), 30 days to 2026-10-01and shape it into a table(columns: rank, project, downloads [PyPI downloads in the 30 days to 2026-10-01], category [our grouping]).Keep the top 150.Build a plotly treemap: category -> package, sized by downloads.- Each category is a neutral frame with a header showing its share (marker.pad.t=22).- Inside each category, fold packages under 0.4% of the total into one lighter "+N more" tile,placed last (sort=False with rows ordered by size).- Gray tiles for every category except "Data & science", which is blue.- Label tiles with the package name and downloads (e.g. "2.46B"); break long hyphenatednames onto two lines; uniformtext minsize 10.- Title with the data and science share, say the grouping is ours in the subtitle.
8. Who operates the satellites in orbit

As of October 17, 2026, Jonathan McDowell's catalog counts 17,038 active satellites in Earth orbit, and 11,137 of them (65.4%) are SpaceX Starlink. Eutelsat OneWeb (652) and Amazon Kuiper (392) are each less than a sixth of Starlink's size, and hatched tiles mark 1,243 military satellites. McDowell notes that "active" is often a judgment call, so the counts are approximate. Data: Jonathan McDowell, GCAT active catalog, October 17, 2026 (operator grouping is ours).
Tip: Starlink is the only color on the page, and marker.pattern.shape="/" marks military satellites without a second color.
Get the data from Jonathan McDowell's GCAT active satellite catalog (planet4589.org/space/gcat)and shape it into a table(columns: owner [GCAT owner code], owner_name, owner_state, class [B commercial, C civil,D defense, A amateur], category [GCAT mission code], satellites [active satellites in Earthorbit, GCAT active catalog as of 2026-10-17]).Build a plotly treemap of active satellites by operator.- Named operator tiles: SpaceX Starlink (SPXS), Eutelsat OneWeb (ONEWEB*), Amazon Kuiper (KUIP),US NRO (NROC), China SatNet (ZXW), Spacesail (YUANX), US Space Force (SFSSC+AFSMC), Planet (PLAN).- Everything else is one "All other operators" parent split by mission and by military vs not.- Starlink is the only colored tile (blue); everything else gray. Hatch military tiles withmarker.pattern.shape="/" and pattern.bgcolor equal to the tile color.- Title with Starlink's share and the total; give the as-of date and source in the subtitle.
Another way to see it: a waffle chart of 100 squares makes Starlink's share literal at 65 blue squares, but the other owners collapse into identical gray squares that can't show mission or military use.
