From 9ee246e7cdc22515b41575016a64f478ac19b0e9 Mon Sep 17 00:00:00 2001 From: pearmini Date: Wed, 10 Sep 2025 08:11:21 -0400 Subject: [PATCH 1/2] Add animals isotype chart --- app/Meta.js | 7 +- app/examples/animals-isotype-chart.recho.js | 208 ++++++++++++++++++++ 2 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 app/examples/animals-isotype-chart.recho.js diff --git a/app/Meta.js b/app/Meta.js index 841da03..4d3b292 100644 --- a/app/Meta.js +++ b/app/Meta.js @@ -11,9 +11,12 @@ export function Meta({example}) { />
- {example.author} + {example.author} / - + {example.title}
diff --git a/app/examples/animals-isotype-chart.recho.js b/app/examples/animals-isotype-chart.recho.js new file mode 100644 index 0000000..0c0d98a --- /dev/null +++ b/app/examples/animals-isotype-chart.recho.js @@ -0,0 +1,208 @@ +/** + * @title How to Create a Animals Isotype Chart? + * @created 2025-09-03 + * @author Bairui Su + * @pull_request 84 + * @github pearmini + * @thumbnail_start 32 + * @ref https://observablehq.com/@observablehq/plot-isotype-chart + */ + +/** + * ============================================================================ + * = 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 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 Reecho, you can + * typically use `recho.require` 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: + * + * 1. Map animals types to their corresponding emojis. + * 2. Map the counts to the number of emojis. + * 3. Generate 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 bars 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 bars look 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"), +); From ed7d3511f8eafda71af8ab305f29e7d46ff9ef5c Mon Sep 17 00:00:00 2001 From: pearmini Date: Wed, 10 Sep 2025 08:19:13 -0400 Subject: [PATCH 2/2] Optimize --- app/examples/animals-isotype-chart.recho.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/examples/animals-isotype-chart.recho.js b/app/examples/animals-isotype-chart.recho.js index 0c0d98a..ee37760 100644 --- a/app/examples/animals-isotype-chart.recho.js +++ b/app/examples/animals-isotype-chart.recho.js @@ -18,7 +18,7 @@ * 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 in echoing intermediate results, helping you to understand the + * 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 @@ -70,8 +70,8 @@ const data = [ * Importing D3 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * Then we import D3 to help us with the data processing. In Reecho, you can - * typically use `recho.require` to import an external library. + * 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/ @@ -84,11 +84,11 @@ const d3 = recho.require("d3"); * Generating the bars * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * - * We'll get started with generating the bars. There are three main tasks: + * We'll get started with generating the bars. There are three main tasks here: * - * 1. Map animals types to their corresponding emojis. - * 2. Map the counts to the number of emojis. - * 3. Generate the bars based on the emojis and the number. + * 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: */ @@ -108,7 +108,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 bars we got so far. */ +/** This is the chart we got so far. */ //➜ 🐖 //➜ 🐄 🐄 🐄 🐄 @@ -140,7 +140,7 @@ 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 bars look like this. */ +/** Now the chart looks like this. */ //➜ pigs -| 🐖 //➜ cattle -| 🐄 🐄 🐄 🐄 @@ -159,7 +159,6 @@ echo(rows.join("\n")); * 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