*! version 1.0 25mar2022

waffle -- Draw waffle charts

Syntax

waffle varlist [if] [in] [, options]

Waffle Design
wide change square shape to wide rectangle

by(varlist) produce multiple waffle charts by categorical varlist

colors(colorlist) specify colors of each category separated by a space; default colors are Tableau palette

emptycolors(colorlist) specify the color of empty squares; default is (gs14)

outlinecolors(colorlist) specify the color of the square outlines; default is (none)

emptyoutlinecolors(colorlist) specify the color of the empty square outlines; default is (none)

markersize(numlist) change the size of the squares; defaults have been determined by other options specified

scheme(schemename) set the scheme for your chart

Add Information
title(tinfo) overall title, can use title options from twoway

note(tinfo) include a note at the bottom of your chart

name(tinfo) name your chart to reference later. Can be used the same way as twoway naming options

legend:([contents] [location]) include and format a legend; available only if multiple variables specified

Misc.
coolsgraph draw a Cool S Graph instead!!

Menu

Graphics > Twoway graph (scatter, line, etc.)

Description

waffle is a wrapper for twoway scatter and draws waffle charts based on variables containing percents or decimals. The standard waffle chart will be a 10x10 grid with colored squares indicating the percent value; specifying
wide will make the grid 5x20.
If only one variable is listed in varlist, by() is allowed and will make a different waffle chart for each category of by(). You can specify up to 5 variables in varlist and indicate the colors of each category.
Other twoway options not listed here are not allowed because waffle charts rely on specific options of twoway being specified.

Options

Waffle Design

wide transforms the 10x10 grid default to a 5x20 grid for all waffles being drawn.

by(varlist) produces a waffle chart for each category in varlist. This option is not allowed if more than one variable is listed in by() and is also not allowed with more than one percent/decimal specified.
This feature will hopefully be resolved soon! If you would like multiple waffle charts with multiple color categories, I recommend drawing multiple individually and combining using graph combine or
the user-written command grc1leg. Can be used with select twoway by() options, such as rows().

colors(colorlist) allows you to specify the colors of your percent/decimal variables. Colors will be assigned in order of your specified varlist. Default colors are based on the Tableau scheme from schemepack.

emptycolors(colorlist) allows you to specify the colors of the "empty" squares in the waffle. The empty squares are all squares up to 100 not included in your defined percent/decimal variables. The default is gs14.

outlinecolors(colorlist) allows you to specify the outline colors of your filled in waffle squares. The default is none.

emptyoutlinecolors(colorlist) allows you to specify the outline colors of the "empty" squares in the waffle. This is separated from outlinecolors in the event that you would like to make the empty squares white with an outline, etc.

markersize(numlist) allows you to alter the size of the markers. The default sizes are based on other options, designed to adjust for number of categories in by() and whether or not wide is specified. The size is also dependent on the aspect ratio, which changes depending on the wide specification.

scheme(schemename) allows you to change the scheme of the chart. Because other graph aspects, such as axes, are not allowed, this mostly determines the look of the background and the legend.
A recommended scheme is white_tableau from schemepack (available on ssc).

Add Information

title(tinfo) allows you give your chart a title. If by() is specified, this will be the overall title, with individual waffle titles being identified by the value labels in by(varlist).

note(tinfo) adds a note at the bottom left of the chart.

name(name [, replace]) gives the chart a name Stata will recognize, which is important if you would like to combine multiple graphs.

legend(contents, location) determines the look of a legend. All legend options allowed in twoway are allowed here.
This option is only available if multiple categories are specified.

Misc.

coolsgraph transports you back in time!

Examples

Example 1 Recreate example from Asjad Naqvi's original post

First pull in data and create percent variables and other data cleaning

. ssc install schemepack, replace

. set scheme white_tableau

. graph set window fontface "Arial Narrow"

. import delim using "https://covid.ourworldindata.org/data/owid-covid-data.csv", clear

. gen date2 = date(date, "YMD")

. format date2 %tdDD-Mon-yy

. drop date

. ren date2 date

. ren location country

. keep iso_code continent country date people_fully_vaccinated population

. keep if length(iso_code) > 3

. drop if inlist(iso_code,"OWID_KOS","OWID_CYN","OWID_HIC","OWID_LIC","OWID_LMC","OWID_UMC")

. bysort country: egen last = max(date) if people_fully_vaccinated != .

. keep if date == last

. summ date

. global dateval: di %tdd_m_y `r(max)'

. di "$dateval"

. gen share = people_fully_vaccinated / population

. gen country2 = country + " (" + string(share * 100, "%9.1f") + "%)"

Now we can use the waffle command for the rest

. waffle share,

. by(country2, rows(2)) markersize(2)

. title("Share of population fully vaccinated", margin(medlarge))

. note("Source: Our World in Data. Data updated: $dateval.")

Example 2 Using Stata's Census 2000 data to show whole range of waffle command

First pull in and prep data

. sysuse pop2000, clear

create another category variable

. gen small_age_cat = 0

. replace small_age_cat = 1 if inrange(agegrp,1,6)

. replace small_age_cat = 2 if inrange(agegrp,7,13)

. replace small_age_cat = 3 if inrange(agegrp,14,17)

. label define age_cat 1 "Under 30" 2 "30-64" 3 "65 & up"

. lab val small_age_cat age_cat

create total percents, regardless of category

. foreach x in black white asian total

. egen tot_`x' = sum(`x')

. gen pct_tot_black = tot_black / tot_total

. gen pct_tot_white = tot_white / tot_total

. gen pct_tot_asian = tot_asian / tot_total

create percents based on two different age categories

. egen small_age_tot_total = sum(total), by(small_age_cat)

. foreach x in white black asian

. gen pct_`x'_age = `x' / total

. egen small_age_tot_`x' = sum(`x'), by(small_age_cat)

. gen pct_`x'_small_age = small_age_tot_`x' / small_age_tot_total

. drop small_age_tot_`x'

keep just categorical variables and percents

. drop total-femisland tot_black-tot_total small_age_tot_total

Create a simple waffle chart of the total share of Black population in Census 2000

. waffle pct_tot_black

try it in wide mode

. waffle pct_tot_black, wide

add a title with correct margins, a note, and change the colors, outlines, and size of the squares

. waffle pct_tot_black, ///

. title("Share of Black U.S. population in 2000 Census", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(6) colors(teal) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5)

look at share of Black population by age group

. waffle pct_black_age, by(agegrp)

works with string category variables too

. waffle pct_black_age, by(agestr)

now smaller age group

. waffle pct_black_small_age, by(small_age_cat)

let's put them on one row

. waffle pct_black_small_age, by(small_age_cat, rows(1))

now add title, note, size and color adjustments

. waffle pct_black_small_age, by(small_age_cat, rows(1)) ///

. title("Share of Black U.S. population in 2000 Census by Age", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(4) colors(teal) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5)

now look at a multi-waffle in wide mode

. waffle pct_black_small_age, by(small_age_cat, rows(3)) ///

. title("Share of Black U.S. population in 2000 Census by Age", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(3) colors(teal) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5) wide

Create a multi-category waffle chart

. waffle pct_tot_black pct_tot_white pct_tot_asian

add a legend, title, note, size and color adjustments

. waffle pct_tot_black pct_tot_white pct_tot_asian, ///

. title("Racial/ethnic composition of the U.S. in 2000", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(5) colors(ltblue teal navy) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5) ///

. legend(order(1 "Black" 2 "White" 3 "Asian" 4 "Other") pos(6) rows(1))

create this multi_category waffle for a specific age range

. waffle pct_black_small_age pct_white_small_age pct_asian_small_age if small_age_cat == 1, ///

. title("Racial/ethnic composition of the U.S. in 2000 under age 30", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(5) colors(ltblue teal navy) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5) ///

. legend(order(1 "Black" 2 "White" 3 "Asian" 4 "Other") pos(6) rows(1))

try it in wide mode

. waffle pct_black_small_age pct_white_small_age pct_asian_small_age if small_age_cat == 1, ///

. title("Racial/ethnic composition of the U.S. in 2000 under age 30", margin(medlarge)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(6) colors(ltblue teal navy) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5) ///

. legend(order(1 "Black" 2 "White" 3 "Asian" 4 "Other") pos(6) rows(1)) wide

store the charts and use graph combine to create a multi-waffle with multiple categories

. preserve

. duplicates drop pct_black_small_age pct_white_small_age pct_asian_small_age small_age_cat, force

. forvalues i = 1/3

. local l = small_age_cat[`i']

. local lbe : value label small_age_cat

. local title : label `lbe' `l'

. waffle pct_black_small_age pct_white_small_age pct_asian_small_age if small_age_cat == `i', ///

. title("`title'", margin(medsmall)) ///

. note("Data from the U.S. 2000 Census") ///

. markersize(3) colors(ltblue teal navy) emptycolors(white) outlinecolors(gs5) emptyoutlinecolors(gs5) ///

. legend(order(1 "Black" 2 "White" 3 "Asian" 4 "Other") pos(6) rows(1)) wide name(waffle_`i', replace)

. restore

. graph combine waffle_1 waffle_2 waffle_3

combine using a single legend with user-written grc1leg

. ssc install grc1leg, replace

. grc1leg waffle_1 waffle_2 waffle_3, cols(1) imargin(zero) ///

. title("Racial/ethnic composition of the U.S. in 2000 by age")

Author

Jared Colston

Educational Leadership & Policy Analysis, University of Wisconsin-Madison

colston@wisc.edu

jaredcolston.com

March 2022

Reference

Initial code for developing waffle charts in Stata come from Asjad Naqvi, found here:

https://medium.com/the-stata-guide/stata-graphs-waffle-charts-32afc7d6f6dd