How to Create a Treemap in ggplot2
Treemaps display hierarchical data as nested rectangles, where each rectangle's area represents a quantitative value. Unlike traditional tree diagrams that emphasize relationships through connecting...
Key Insights
- Treemaps excel at visualizing hierarchical data with proportional areas, making them ideal for budget breakdowns, market share analysis, and organizational structures where both hierarchy and magnitude matter.
- The
treemapifypackage extends ggplot2 with specialized geoms that handle the complex rectangle-packing algorithm, letting you create treemaps using familiar ggplot2 syntax and layering. - Nested treemaps with proper borders and labeling require careful parameter tuning—use
subgroupfor hierarchy levels and always test label readability at your target output size.
Introduction to Treemaps
Treemaps display hierarchical data as nested rectangles, where each rectangle’s area represents a quantitative value. Unlike traditional tree diagrams that emphasize relationships through connecting lines, treemaps prioritize space efficiency and magnitude comparison. You’ll find them particularly effective when visualizing budget allocations, file system storage, market capitalization by sector, or any scenario where you need to show both categorical hierarchy and proportional size simultaneously.
The treemapify package brings treemap functionality to ggplot2, maintaining the grammar of graphics approach while handling the complex rectangle-packing algorithms behind the scenes. This means you get treemaps that integrate seamlessly with your existing ggplot2 workflow, including themes, color scales, and layering capabilities.
Setup and Required Packages
Install both packages if you haven’t already:
install.packages("ggplot2")
install.packages("treemapify")
For this article, we’ll use a company budget dataset that demonstrates typical hierarchical data:
library(ggplot2)
library(treemapify)
# Create sample company budget data
company_budget <- data.frame(
department = c("Engineering", "Engineering", "Engineering",
"Sales", "Sales", "Marketing", "Marketing",
"Operations", "Operations"),
team = c("Backend", "Frontend", "DevOps",
"Enterprise", "SMB", "Digital", "Content",
"HR", "Finance"),
budget = c(2500000, 1800000, 1200000,
2000000, 1500000, 1300000, 800000,
900000, 700000),
headcount = c(45, 32, 18, 28, 22, 15, 10, 12, 8)
)
This dataset has a clear hierarchy (department → team) with quantitative measures (budget and headcount) that we can visualize effectively with treemaps.
Creating a Basic Treemap
The core function is geom_treemap(), which requires at minimum an area aesthetic to determine rectangle sizes. Add fill to color-code categories and you have a functional treemap:
ggplot(company_budget, aes(area = budget, fill = department)) +
geom_treemap()
This creates a space-filling layout where each rectangle’s area is proportional to the budget value. The algorithm automatically arranges rectangles to minimize wasted space while maintaining readability. The fill aesthetic colors rectangles by department, making it easy to identify which areas belong to which category.
By default, treemapify uses a “squarified” algorithm that tries to create rectangles as close to square as possible, improving readability compared to simple slicing approaches.
Adding Labels and Customization
An unlabeled treemap is nearly useless. Add geom_treemap_text() to overlay labels:
ggplot(company_budget, aes(area = budget, fill = department, label = team)) +
geom_treemap() +
geom_treemap_text(
colour = "white",
place = "centre",
size = 15,
grow = FALSE
) +
scale_fill_brewer(palette = "Set2") +
labs(
title = "Company Budget Allocation by Team",
fill = "Department"
) +
theme(legend.position = "bottom")
Key parameters for geom_treemap_text():
colour: Text color (white works well on darker fills)place: Position within rectangles (“centre”, “topleft”, “bottomright”, etc.)size: Base text size in pointsgrow: If TRUE, text grows to fill available space (often too aggressive)
The scale_fill_brewer() function applies a ColorBrewer palette, providing better color differentiation than ggplot2’s defaults. For professional outputs, consider using your organization’s brand colors with scale_fill_manual().
Creating Nested/Hierarchical Treemaps
The real power of treemaps emerges with hierarchical data. Use the subgroup aesthetic to create visual groupings:
ggplot(company_budget,
aes(area = budget,
fill = department,
subgroup = department,
label = team)) +
geom_treemap() +
geom_treemap_subgroup_border(colour = "white", size = 3) +
geom_treemap_subgroup_text(
place = "centre",
grow = FALSE,
alpha = 0.5,
colour = "black",
fontface = "bold",
min.size = 0
) +
geom_treemap_text(
colour = "white",
place = "centre",
size = 12,
grow = FALSE
) +
scale_fill_brewer(palette = "Set2") +
labs(title = "Company Budget: Department and Team Breakdown") +
theme(legend.position = "none")
This creates a two-level hierarchy where departments form larger groups containing individual team rectangles. The geom_treemap_subgroup_border() adds thick white borders around department groups, providing clear visual separation.
For deeper hierarchies, add subgroup2 and subgroup3:
# Example with three-level hierarchy
org_data <- data.frame(
division = rep(c("North America", "Europe"), each = 6),
department = rep(c("Engineering", "Sales", "Marketing"), 4),
team = paste("Team", 1:12),
revenue = runif(12, 100000, 5000000)
)
ggplot(org_data,
aes(area = revenue,
fill = department,
subgroup = division,
subgroup2 = department,
label = team)) +
geom_treemap() +
geom_treemap_subgroup_border(
aes(subgroup = division),
colour = "black",
size = 5
) +
geom_treemap_subgroup_border(
aes(subgroup = subgroup2),
colour = "white",
size = 2
) +
geom_treemap_text(colour = "white", place = "centre", size = 10)
Advanced Styling and Polish
Production-ready treemaps need careful styling. Here’s a fully polished example:
ggplot(company_budget,
aes(area = budget,
fill = budget,
subgroup = department,
label = paste0(team, "\n$",
format(budget/1000000, digits = 2), "M"))) +
geom_treemap() +
geom_treemap_subgroup_border(colour = "white", size = 4) +
geom_treemap_subgroup_text(
aes(label = department),
place = "top",
colour = "grey20",
alpha = 0.7,
grow = FALSE,
fontface = "bold",
size = 14
) +
geom_treemap_text(
colour = "white",
place = "centre",
size = 10,
grow = FALSE,
lineheight = 0.9
) +
scale_fill_gradient(
low = "#d4e6f1",
high = "#1a5490",
labels = scales::dollar_format(scale = 1e-6, suffix = "M")
) +
labs(
title = "2024 Annual Budget Allocation",
subtitle = "By department and team",
fill = "Budget",
caption = "Source: Finance Department | Data as of Q4 2024"
) +
theme_minimal() +
theme(
plot.title = element_text(size = 18, face = "bold"),
plot.subtitle = element_text(size = 12, color = "grey40"),
plot.caption = element_text(size = 8, color = "grey50"),
legend.position = "right"
)
This example demonstrates several refinements:
- Gradient fill based on budget values for additional visual encoding
- Multi-line labels with formatted currency values
- Department labels positioned at the top of each group
- Comprehensive title, subtitle, and caption
- Custom theme adjustments for typography
Common Use Cases and Best Practices
Treemaps work best when:
- You have 10-100 items to visualize (too few wastes space, too many becomes cluttered)
- Proportional area comparison is more important than precise value reading
- Your hierarchy has 2-3 levels maximum
- Categories have meaningful size differences (avoid many tiny rectangles)
Avoid treemaps when:
- Precise value comparison is critical (use bar charts instead)
- Your data has negative values (treemaps require positive areas)
- Categories are roughly equal in size (creates uniform, boring layouts)
- You need to show trends over time (use line or area charts)
Here’s a comparison showing when to choose alternatives:
library(patchwork)
# Treemap version
p1 <- ggplot(company_budget,
aes(area = budget, fill = department, label = team)) +
geom_treemap() +
geom_treemap_text(colour = "white", size = 10) +
labs(title = "Treemap: Good for hierarchy + proportion") +
theme(legend.position = "none")
# Bar chart alternative
p2 <- ggplot(company_budget,
aes(x = reorder(team, budget), y = budget, fill = department)) +
geom_col() +
coord_flip() +
scale_y_continuous(labels = scales::dollar_format()) +
labs(title = "Bar chart: Better for precise comparison",
x = NULL, y = "Budget") +
theme_minimal() +
theme(legend.position = "none")
p1 / p2
Data preparation tips:
- Aggregate small categories into “Other” if they create tiny rectangles
- Ensure your area variable is always positive
- Pre-calculate percentages or formatted labels before plotting
- Test different
subgrouparrangements to find the most intuitive hierarchy
Treemaps excel at revealing the “big picture” of hierarchical data. When you need stakeholders to immediately grasp budget distributions, market compositions, or organizational structures, a well-crafted treemap communicates more effectively than tables or traditional charts. Use the techniques in this article to create treemaps that are both informative and visually compelling.