
Created 2025-09-03
/**
* ============================================================================
* = How to Create a Animals Isotype Chart? =
* ============================================================================
*
* > Ref. https://observablehq.com/@observablehq/plot-isotype-chart
*
* Recho is suitable for Isotype Chart (Unit Chart), because it allows you to
* encode data as characters easily. This sketch shows how to create a animals
* isotype chart step by step. It's also a good example to show that Recho is
* powerful in echoing intermediate results, helping you to understand the
* data and the process of creating the chart.
*
* The final chart looks like below, which tells us about the live stock of
* animals in Great Britain and United States. Compared to Great Britain, the
* United States has more cattle and pigs, with pig showing the most dramatic
* difference. In Great Britain, sheep are more prominent, which may related to
* the country's geography and dietary traditions, such as the wool industry
* and lamb consumption.
*/
//➜
//➜ Great Britain
//➜ pigs -| 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜
//➜ United States
//➜ pigs -| 🐖 🐖 🐖 🐖 🐖 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜
//➜ Live stock (millions)
//➜
echo(output);
/**
* Next, let's dive into how `output` is generated.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Preparing the data
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* First, we need to prepare the data. We're going to use the following dataset
* to create the chart. It's a tiny tubular dataset, with each row representing
* a animal in a country and the count of the animal.
*/
const data = [
{animal: "pigs", country: "Great Britain", count: 1354979},
{animal: "cattle", country: "Great Britain", count: 3962921},
{animal: "sheep", country: "Great Britain", count: 10931215},
{animal: "pigs", country: "United States", count: 6281935},
{animal: "cattle", country: "United States", count: 9917873},
{animal: "sheep", country: "United States", count: 7084151},
];
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Importing D3
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Then we import D3 to help us with the data processing. In Recho, you can
* typically use `recho.require(name)` to import an external library.
*
* > Ref. https://recho.dev/docs/libraries-imports
* > Ref. https://d3js.org/
*/
const d3 = recho.require("d3");
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Generating the bars
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* We'll get started with generating the bars. There are three main tasks here:
*
* 1. Mapping animals types to their corresponding emojis.
* 2. Mapping the counts to the number of emojis.
* 3. Generating the bars based on the emojis and the number.
*
* Here is the implementation:
*/
//➜ [ 0, 1, 2, 3, 4, 5 ]
const I = echo(d3.range(data.length));
//➜ { cattle: "🐄", sheep: "🐑", pigs: "🐖" }
const emoji = echo({cattle: "🐄", sheep: "🐑", pigs: "🐖"});
//➜ [ "🐖", "🐄", "🐑", "🐖", "🐄", "🐑" ]
const E = echo(data.map((d) => emoji[d.animal]));
//➜ [ 1, 4, 11, 6, 10, 7 ]
const V = echo(data.map((d) => Math.round(d.count / 1e6)));
//➜ [ "🐖 ", "🐄 🐄 🐄 🐄 ", "🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 ", "🐖 🐖 🐖 🐖 🐖 🐖 ", "🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 ", "🐑 🐑 🐑 🐑 🐑 🐑 🐑 " ]
const bars = echo(I.map((i) => `${E[i]} `.repeat(V[i])));
/** This is the chart we got so far. */
//➜ 🐖
//➜ 🐄 🐄 🐄 🐄
//➜ 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜ 🐖 🐖 🐖 🐖 🐖 🐖
//➜ 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄
//➜ 🐑 🐑 🐑 🐑 🐑 🐑 🐑
echo(bars.join("\n"));
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Adding the labels
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Next step is to add the labels to the bars. We need to collect all the
* animal types by a set, and compute a margin left to make sure the labels
* are aligned. Then concatenate the labels to the bars with a separator: `-|`.
*/
//➜ [ "pigs", "cattle", "sheep" ]
const L = echo(Array.from(new Set(data.map((d) => d.animal))));
//➜ 6
const marginLeft = echo(d3.max(L, (d) => d.length));
//➜ [ " pigs", "cattle", " sheep", " pigs", "cattle", " sheep" ]
const labels = echo(data.map((d) => d.animal.padStart(marginLeft, " ")));
//➜ [ " pigs -| 🐖 ", " cattle -| 🐄 🐄 🐄 🐄 ", " sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 ", " pigs -| 🐖 🐖 🐖 🐖 🐖 🐖 ", " cattle -| 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 ", " sheep -| 🐑 🐑 🐑 …
const rows = echo(I.map((i) => " " + labels[i] + " -| " + bars[i]));
/** Now the chart looks like this. */
//➜ pigs -| 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜ pigs -| 🐖 🐖 🐖 🐖 🐖 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑
echo(rows.join("\n"));
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Generating the titles
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Technically speaking, the chart is a facet chart, which means it contains
* multiple charts. The first one is for Great Britain, and the second one is
* for United States. In order to differentiate the two charts, we need to add
* the titles and some spacing.
*/
//➜ 45
const width = echo(d3.max(rows, (d) => d.length));
//➜ [ "Great Britain", "United States" ]
const T = echo(Array.from(new Set(data.map((d) => d.country))));
//➜ [ " Great Britain", " United States" ]
const titles = echo(T.map((t) => t.padStart(Math.ceil(width / 2 + 2), " ")));
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Final output
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Finally, we can concatenate the titles, the rows, and the live stock caption
* to get the final output!
*/
//➜
//➜ Great Britain
//➜ pigs -| 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜
//➜ United States
//➜ pigs -| 🐖 🐖 🐖 🐖 🐖 🐖
//➜ cattle -| 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄 🐄
//➜ sheep -| 🐑 🐑 🐑 🐑 🐑 🐑 🐑
//➜
//➜ Live stock (millions)
//➜
const output = echo(
[
" ",
titles[0], // Great Britain
...rows.slice(0, 3),
" ",
titles[1], // United States
...rows.slice(3),
" ",
"Live stock (millions)", // Add a caption
" ",
].join("\n"),
);