Charts/Matrix charts
Waffle
<Waffle /> · 10 examples
A grid of squares, filled in order, so a share of a whole is something you can count.
Overview
Tell a room that 37% of its users are on mobile and the room nods. Show it a hundred squares with thirty-seven of them coloured in and the room sees it, because the human visual system is better at counting small things than at judging the angle of a pie slice. That is the whole case for the waffle chart.
It is the pie chart's friendlier cousin, named for the grid it looks like on the plate, and it has become a favourite of infographic designers and newsrooms. The classic form is ten rows by ten columns, so every square is exactly one percent, and the reader never needs a ruler or a calculator. It also survives the thing that quietly destroys pie charts, which is having an audience that cannot judge angles but can count.
It does have one limit worth knowing before you start: a waffle is a part-to-whole picture of a single whole. It shows you what share each category has, and nothing else. For that job it is hard to beat, for anything harder, it will politely stay quiet.
Props
API
<Waffle data={mix} name={|s: &Share| s.name} value={|s: &Share| s.value} />| Prop | Type | Default |
|---|---|---|
data | as above | required |
name | Fn(&T) -> &str | required |
value | Fn(&T) -> f64 | required |
rows, columns | usize | 10, 10 |
gap | f32: the space between squares, as a share of a square | 0.12 |
legend | Legend | shown |
tooltip, class |
Each item gets a share of the rows × columns squares, filled in order, row by row. Shares are rounded by the largest-remainder method, so the squares always add up to the full grid.
Run them
10 examples
Press Run to load an example into the live render at the top of the page. Open one to read its code.
How to read it
- 01Count squares of one colour. On the default 10 by 10 grid, each square is 1% of the whole.
- 02Read the grid in reading order: the first category in your data starts at the top left and the later ones follow.
- 03Compare blocks by how many rows they fill, not by area impressions. A block of 20 squares is two rows, easy to see.
- 04Hover a square for its category name, and use the legend to switch categories off.
When to use it, and when not to
Reach for it when
- You want to show a handful of shares of one whole and have people take away the number: 12% of orders, 37% on mobile.
- The audience is general, or in a hurry, or both. Counting squares needs no training.
- You want a percentage to feel like people. A grid of a hundred can stand for a hundred users, and that is a different message from a slice.
- You have between two and six categories. That is where colours stay distinguishable and the blocks stay chunky.
Skip it when
- Differences between shares are small. Two blocks of 31 and 33 squares look alike, and the chart cannot help. A sorted bar chart is sharper.
- There are many categories. Past about six, colours blur and tiny categories shrink to one or two squares that nobody can find.
- You need to compare shares across several totals. The chart shows one whole at a time. Use a Mekko when the size of the whole varies too.
- You need exactness beyond a square. At 10 by 10 the resolution is 1%. A share of 0.4% rounds to zero or to one full square, depending on the leftovers.
The math behind it
From values to squares
You pass one row per category, each with a name and a value . Only finite, positive values count; anything else gets zero squares. With a grid of rows and columns (default ) there are squares to hand out, and each category's exact share of them is proportional to its value.
Squares are whole objects, so the exact shares have to be rounded, and rounding each one on its own makes the total drift: three equal categories on 100 squares would each get 33, and a square would be left over. The chart uses the largest-remainder method.
Largest remainder
Every category first gets squares, the whole part of its share. The squares that are left, , are handed out one each to the categories with the largest fractional parts , in descending order. Only categories with a positive value are eligible.
The result always adds up to exactly squares, and no category is ever more than one square away from its exact share. For three equal categories on 100 squares the counts are 34, 33 and 33, and which one gets the extra is decided by the order of the data. If every value is zero or missing, nothing is filled.
Layout
Categories are laid out in the order of your data, filling the grid row by row from the top left: the first category takes the first squares, the second takes the next , and so on. Squares not given to anybody (when there is nothing to show) are left empty. The gap (default 0.12) is the space between squares as a share of a square, clamped to 0 through 0.9.
This means that the order you pass is the order you read. Sort largest first and the biggest block anchors the top left. Leave the order alone if it has a meaning, such as a funnel stage or a time period.
Real life usage
A hundred customers, give or take
Hanna led the customer research team at an online bookshop that was famous within the company for a monthly all-hands in which one slide, one slide only, had to answer "who actually buys from us?". Her predecessor had used a pie chart with seven slices, and nobody had ever been able to say what the fifth one was.
The data was good. A survey of 2,300 customers sorted them into how they usually bought: 41% for themselves, 23% as gifts, 17% for a book club, 11% for school or work, 6% for a child, and 2% who answered "other" and, in the comments, "it is complicated".
The problem with these numbers was not accuracy. It was that nobody remembered them. The finance director had once recalled the "gifts" slice as "about half", and that went into a planning document, where it lived for a quarter.
What she wanted was a picture where 41% looked like forty-one of something, and where a person could look away, look back, and still count. She also wanted the 2% to be visible without a magnifier and to be honest about being small.
She built the slide with a <Waffle> from zopra-charts: name, value, the survey shares, the default 10 by 10 grid. The component rounded 41, 23, 17, 11, 6 and 2 to squares that totalled exactly one hundred. The 2% sat at the bottom right as two squares that people noticed and mentioned at the end of the meeting.
The slide got the first laughs a market-research presentation in that building had ever had. Someone counted the gift squares aloud and got 23 on the first try, and a person from logistics said he finally knew what to do with the gift-wrap budget. In the next planning round the "about half" had become "23%", and the wrapping line was cut by a third.
The finance director has asked for every share-of-whole slide to be a waffle since. He has not asked about the two squares, but he looks at them.
Pitfalls
- Rounding is visible. The squares sum to exactly the grid, but a category's share is rounded to the nearest square. On a 10 by 10 grid, 12.4% and 11.6% both become 12 squares.
- Tiny categories. A share below half a square can end up with zero squares or with one, depending on how the leftovers fall. Group tiny categories into "Other" so the chart is not deciding for you.
- Order carries a message. Blocks fill from the top left in data order, and the eye treats the first as the most important. Sort on purpose.
- A waffle is not a time series. Two waffles side by side for two periods are fine for a quick before-and-after, for more than two, switch to a chart whose axis is time.
From around the web