calligram for Stata

Word clouds in any shape, from survey text to maps. Every example below is a real page written by Stata: open one, then search, filter, hover, zoom, click the key, switch groups and save pictures.

Get it on GitHubRead the guide
net install calligram, from("https://raw.githubusercontent.com/fahad-mirza/calligram_Stata/main/") net get calligram, from("https://raw.githubusercontent.com/fahad-mirza/calligram_Stata/main/") // example data

Click any picture to open its interactive page.

Survey responses

Survey responses

The basics: 16 open-ended answers, cleaned, counted and packed so no two words touch.

Stata code
calligram, textvar(response) minfreq(1)
Open the interactive page →
A title, a light background and a gradient

A title, a light background and a gradient

Colours run from the most to the least frequent word.

Stata code
calligram, textvar(response) minfreq(1) bgcolor(white) ///
    gradient(#1d3557 #e63946) title("What customers said")
Open the interactive page →
Rotated words, another font

Rotated words, another font

Seven fonts are bundled, so the page looks the same on every computer.

Stata code
calligram, textvar(response) minfreq(1) rotate(random) font(Roboto)
Open the interactive page →
A heart

A heart

Nine shapes are built in: rectangle, ellipse, circle, square, cloud, heart, diamond, triangle and star.

Stata code
use cg_inaugural, clear
calligram, textvar(text) shape(heart) width(1000) height(900) ///
    maxwords(250) rotate(random)
Open the interactive page →
A star with its outline

A star with its outline

outline draws the edge of the shape behind the words.

Stata code
calligram, textvar(text) shape(star) outline width(1000) height(1000) ///
    maxwords(250) font(Lato)
Open the interactive page →
Any shape from coordinates

Any shape from coordinates

Points saved as _ID, _X, _Y form a one-area shapefile; the outline is exact.

Stata code
calligram, textvar(text) shapes(cg_blob_shp.dta) projection(none) outline ///
    width(1000) height(1000) maxwords(300) phrases rotate(90) font(Roboto)
Open the interactive page →
... or from a picture

... or from a picture

Any black-on-white image works as a mask, including a Stata graph you export.

Stata code
graph export cg_mask_blob.png, width(1000) replace
calligram, textvar(text) mask(cg_mask_blob.png) outline ///
    width(1000) height(1000) maxwords(300) rotate(random) font(Lato)
Open the interactive page →
Every city inside its own country

Every city inside its own country

A world shapefile and each city's latitude and longitude; size shows population.

Stata code
use cg_cities, clear
calligram, wordvar(city) countvar(population) shapes(cg_countries_shp.dta) ///
    location(lat lon) outline outlinewidth(1) outlinecolor(#b8b8b8)  ///
    width(2400) height(1067) maxwords(1207) minfreq(1) minfontsize(4) ///
    margin(2) font(Lato) bgcolor(white)
Open the interactive page →
... and each near its real location

... and each near its real location

near places every city as close as it can to its own point.

Stata code
calligram, wordvar(city) countvar(population) shapes(cg_countries_shp.dta) ///
    location(lat lon) near outline ...
Open the interactive page →
A continent, cut with ordinary Stata commands

A continent, cut with ordinary Stata commands

keep and merge on the shapefile give any region you like.

Stata code
use cg_countries, clear
keep if continent == "Africa"
keep _ID
merge 1:m _ID using cg_countries_shp, keep(match) nogenerate
save africa_shp, replace
use cg_cities, clear
calligram if continent == "Africa", wordvar(city) countvar(population) ///
    shapes(africa_shp.dta) location(lat lon) outline width(900) height(1280)
Open the interactive page →
Africa with turned words

... with words turned to fill each country

rotate(random) lets city names run along tall or narrow countries, so countries with few cities are less empty.

Stata code
calligram if continent == "Africa", wordvar(city) countvar(population) ///
    shapes(africa_shp.dta) location(lat lon) outline rotate(random)
Open the interactive page →
Two-word phrases

Two-word phrases

phrases finds pairs such as "united states" and "fellow citizens" and shows each as one entry.

Stata code
use cg_inaugural, clear
calligram, textvar(text) phrases maxwords(200) font(Merriweather) ///
    title("US inaugural addresses, 1789-2025")
Open the interactive page →
One cloud per group

One cloud per group

by() puts each group in its own tab, and image() writes one picture per group.

Stata code
calligram, textvar(text) by(century) phrases maxwords(120) font(Merriweather)
Open the interactive page →
A book in a circle

A book in a circle

Alice's Adventures in Wonderland, with "mock turtle", "march hare" and "white rabbit" found as phrases.

Stata code
use cg_alice, clear
calligram, textvar(text) phrases shape(circle) width(1000) height(1000) ///
    maxwords(250) minfreq(3) rotate(random) font(Merriweather) ///
    bgcolor(#fdfaf3) gradient(#7b2d26 #33658a)
Open the interactive page →
Words already counted

Words already counted

wordvar() and countvar(): car makes in sysuse auto, sized by total price.

Stata code
sysuse auto, clear
gen brand = word(make, 1)
calligram, wordvar(brand) countvar(price) minfreq(1) nostopwords ///
    shape(ellipse) font(Open Sans) bgcolor(white)
Open the interactive page →
Survey weights

Survey weights

Every word counts with its response's weight (aweight, fweight).

Stata code
calligram [aweight = weight], textvar(response) minfreq(1)
Open the interactive page →
The results as a dataset

The results as a dataset

saving() keeps every word with its count, size, position and colour.

Stata code
calligram, textvar(text) phrases maxwords(100) saving(words, replace)
use words, clear
list rank word count fontsize in 1/10
Open the interactive page →
3 million words in under a second

3 million words in under a second

80,000 paragraphs, counted on all processor cores.

Stata code
use cg_inaugural, clear
expand 50
calligram, textvar(text)
Open the interactive page →
Smaller pages with online

Smaller pages with online

Words as text with the font from Google Fonts: much smaller files, needs internet.

Stata code
calligram, textvar(text) online font(Lato) maxwords(200)
Open the interactive page →
Colour by a number

Colour by a number

Each word gets the average year of the addresses it appears in.

Stata code
calligram, textvar(text) colorby(year) gradient(#d95f02 #5e3c99) phrases ///
    maxwords(200) font(Merriweather)
Open the interactive page →
Colour by group

Colour by group

Each word takes the colour of the century it is most typical of; click the key to hide a group.

Stata code
calligram, textvar(text) colorby(century) phrases maxwords(200) font(Merriweather)
Open the interactive page →
Groups from value labels

Groups from value labels

A labelled variable gives the categories and their names.

Stata code
sysuse auto, clear
gen brand = word(make, 1)
calligram, wordvar(brand) countvar(price) colorby(foreign) minfreq(1) ///
    nostopwords shape(ellipse) font(Open Sans) bgcolor(white)
Open the interactive page →
Colours from a picture

Colours from a picture

Each word takes the average colour of the picture under its letters.

Stata code
calligram, textvar(text) shape(heart) colorimage(stripes.png) ///
    width(1000) height(900) maxwords(250) rotate(random) bgcolor(white)
Open the interactive page →
Every writing system

Every language and writing system

20 languages, 12 writing systems: right-to-left Arabic and Hebrew, Hindi, Tamil, Thai, Chinese, Japanese, Korean. Click the key to hide a script.

Stata code
use cg_languages, clear
calligram [fweight = responses], textvar(text) colorby(script) ///
    minfreq(1) maxwords(250) scaling(0.35) font(Lato)
Open the interactive page →
Urdu in Nastaliq

Urdu in Nastaliq

Customer comments in Urdu, in Urdu's own calligraphic style, Nastaliq, with the bundled Noto Nastaliq Urdu font.

Stata code
use cg_urdu, clear
calligram [fweight = responses], textvar(text) minfreq(1) ///
    stopwords(اور تھی تھا ہے لیکن مگر بہت ہوئی) ///
    scriptfonts(arabic "Noto Nastaliq Urdu") shape(circle)
Open the interactive page →