Source
90 chart lines · 1 file · 2.1 kBBenchmark harness excluded · shared/mount.ts
English letter frequencies26 records · CSV · 275 B
@charts-poc/demo-data/alphabetSelection: Complete published snapshot
- letter
- string
- frequency
- number
Cryptographical Mathematics by Robert Edward Lewand@observablehq/sample-datasets@1.0.1 · revision 732c0148de74 · alphabet.csv · ISC distribution; upstream source credited · SHA-256 d62ce74dad83Pinned snapshot
cases/41-waffle-unit-chart/tanstack.ts90 lines · entry
cases/41-waffle-unit-chart/tanstack.ts
import { cell, colorLegend, defineChart } from '@tanstack/charts'
import { scaleBand } from 'd3-scale'
import { alphabet } from '@charts-poc/demo-data/alphabet'
import type { AlphabetRow } from '@charts-poc/demo-data/alphabet'
import { tanstackMount } from '../../shared/mount'
interface WaffleCell extends AlphabetRow {
unit: number
column: number
row: number
}
const unitFrequency = 0.01
const colors = [
'#8b5cf6',
'#10b981',
'#ec4899',
'#f97316',
'#2563eb',
'#06b6d4',
]
const letters = alphabet.map((row) => row.letter)
const total = Math.round(
alphabet.reduce((sum, row) => sum + row.frequency, 0) / unitFrequency,
)
const definition = () => {
return defineChart(({ width, height }) => {
const columns = Math.max(
1,
Math.floor(Math.sqrt((total * width) / Math.max(1, height))),
)
const cells = layoutWaffleCells(alphabet, columns)
return {
marks: [
cell(cells, {
x: 'column',
y: 'row',
color: 'letter',
inset: 1,
radius: 2,
}),
],
x: {
scale: () => scaleBand<number>(),
},
y: {
scale: () => scaleBand<number>(),
reverse: true,
},
guides: false,
color: {
domain: letters,
range: colors,
legend: colorLegend({ label: 'Letter' }),
},
}
})
}
export const mount = tanstackMount(
definition,
'English letter frequency waffle chart',
)
function layoutWaffleCells(
rows: readonly AlphabetRow[],
columns: number,
): readonly WaffleCell[] {
const cells: WaffleCell[] = []
let cumulativeFrequency = 0
for (const row of rows) {
const start = Math.round(cumulativeFrequency / unitFrequency)
cumulativeFrequency += row.frequency
const end = Math.round(cumulativeFrequency / unitFrequency)
for (let unit = start; unit < end; unit += 1) {
cells.push({
...row,
unit,
column: unit % columns,
row: Math.floor(unit / columns),
})
}
}
return cells
}