Sparklines
Monday, September 28, 2026
Sometimes a few characters are enough to show the shape of some data. Edward Tufte wrote about this concept in sparkline theory and practice, sharing how very small graphs can provide incredible insight.
I wrote a small sparkline vocabulary for Factor that can turn numbers into little Unicode sparklines:
IN: scratchpad { 0 30 55 80 33 150 } sparkline .
"▁▂▃▄▂█"
Each number becomes one of eight block characters, from ▁ to █.
The smallest value uses the lowest block and the largest uses the highest.
The result is an ordinary string that we can print in a terminal, include
in a table, or put next to a number in a report.
There is also a method that supports comma-separated numbers:
IN: scratchpad "0,30,55,80,33,150" sparkline .
"▁▂▃▄▂█"
Automatic scaling makes a chart fill the available height, but that means two very different sets of numbers can have the same shape:
IN: scratchpad { 10 20 30 } sparkline .
"▁▄█"
IN: scratchpad { 100 200 300 } sparkline .
"▁▄█"
To compare them, we can use sparkline-range with the same minimum and
maximum:
IN: scratchpad { 10 20 30 } 0 300 sparkline-range .
"▁▁▁"
IN: scratchpad { 100 200 300 } 0 300 sparkline-range .
"▃▅█"
Or use the sparklines word to automatically normalize several inputs
that use a shared range:
IN: scratchpad { { 10 20 30 } { 100 200 300 } } sparklines .
{ "▁▁▁" "▃▅█" }
Most of the implementation fits in one word:
SYMBOL: ticks
"▁▂▃▄▅▆▇█" ticks set-global
:: sparkline-range ( seq min max -- str )
max min - ticks get length 1 - / [ 1 ] when-zero :> unit
seq [ min max clamp min - unit /i ticks get nth ] "" map-as ;
We divide the range into intervals, clamp each value, and use integer division to select its character.
Tiny charts, tiny implementation!