Chart guide
Code on the page
Type ``` and Enter for a block of Ruby; Enter three times at its end to leave it. Blocks run top to bottom and share what they define, so data in one block can be charted in the next. A chart shows under its block a moment after you stop typing.
A first chart
Data, then a chart of it. Keywords say what goes where.
visits = dataset month: [ 1, 2, 3, 4, 5, 6 ], patients: [ 42, 51, 48, 63, 70, 74 ] chart :line, visits, x: :month, y: :patients, title: "Patients seen"
Settings in a block
The same settings, one per line. Keywords and a block can be mixed.
visits = dataset month: [ 1, 2, 3, 4, 5, 6 ], patients: [ 42, 51, 48, 63, 70, 74 ] chart :line, visits do title "Patients seen" x :month, label: "Month" y :patients, label: "Patients", from: 0 color :red hline 60, label: "Capacity" caption "Patients seen in clinic each month." end
Data
Typed as CSV
Headers become column names: “Systolic BP” is :systolic_bp, and keeps its heading on axes.
bp = dataset <<~CSV Age,Systolic BP,Arm 34,120,drug 51,135,placebo 62,141,drug CSV
Columns, or rows
A list per column, or a hash per row.
bp = dataset age: [ 34, 51, 62 ], systolic: [ 120, 135, 141 ]
bp = dataset [ { age: 34, systolic: 120 }, { age: 51, systolic: 135 } ]
Choosing and shaping
Every verb gives a new dataset; the old one stays as it was.
trials = dataset week: [ 0, 4, 8, 0, 4, 8 ], arm: %w[ drug drug drug placebo placebo placebo ],
response: [ 0.1, 0.4, 0.6, 0.1, 0.2, 0.25 ]
drug = trials.where(arm: "drug")
later = trials.where { week >= 4 }
means = trials.summarize(by: :arm) { |rows| { mean: rows.mean(:response) } }
percent = trials.derive(:percent) { response * 100 }
puts means.to_a.inspect
Or drop a CSV, TSV or JSON file on the page: it's kept under Data, and a line reading it goes in, like trials = import "trials". A web address works too: import "https://…/cases.csv".
More verbs: sort_by, order, first, count_by, only, except, rename, relabel, join, longer, group_by, and mean, median, sd, quantile, sum, min, max of a column.
Kinds of chart
Line
Change over time. A coloured column makes a line per group, named at its end.
trials = dataset week: [ 0, 4, 8, 12, 0, 4, 8, 12 ], arm: %w[ drug drug drug drug placebo placebo placebo placebo ], response: [ 0.1, 0.35, 0.5, 0.6, 0.1, 0.15, 0.2, 0.22 ] chart :line, trials, x: :week, y: :response, color: :arm, y_format: :percent
Scatter
Two measures against each other; trend adds a least-squares line and R².
patients = dataset bmi: [ 21, 24, 27, 29, 31, 34, 36 ], sbp: [ 118, 121, 128, 131, 137, 142, 149 ] chart :scatter, patients, x: :bmi, y: :sbp, trend: true
Bar
Amounts by category. stack, horizontal and labels change how they sit.
arms = dataset arm: %w[ Placebo Low High ], responders: [ 0.21, 0.38, 0.52 ] chart :bar, arms, x: :arm, y: :responders, labels: true, y_format: :percent
Area
Totals over time; stacked, the parts of a whole.
beds = dataset week: [ 1, 2, 3, 1, 2, 3 ], ward: %w[ ICU ICU ICU General General General ], patients: [ 8, 12, 9, 30, 41, 37 ] chart :area, beds, x: :week, y: :patients, color: :ward, stack: true
Step
Values that hold until they change, like doses.
dose = dataset day: [ 0, 3, 7, 14 ], mg: [ 5, 10, 20, 20 ] chart :step, dose, x: :day, y: :mg
Histogram
How one measure is spread. bins sets how many bars.
ages = dataset age: [ 23, 31, 34, 38, 41, 44, 45, 47, 52, 53, 56, 58, 61, 64, 67, 71, 78 ] chart :histogram, ages, x: :age, bins: 6
Box
Median, quartiles and outliers by group. points shows every value too.
levels = dataset arm: %w[ A A A A A B B B B B ], crp: [ 3, 5, 6, 8, 21, 2, 3, 3, 4, 6 ] chart :box, levels, x: :arm, y: :crp, points: true
Forest
Estimates with intervals, one row each. “Overall” rows are drawn as diamonds.
studies = dataset [
{ study: "Smith 2019", ratio: 0.82, low: 0.61, high: 1.10, n: 120 },
{ study: "Lee 2021", ratio: 0.66, low: 0.51, high: 0.86, n: 300 },
{ study: "Overall", ratio: 0.72, low: 0.60, high: 0.87 }
]
chart :forest, studies, x: :ratio, label: :study, error: { low: :low, high: :high }, size: :n, log: :x
Survival
Kaplan–Meier curves from follow-up times and events, with a log-rank p.
cohort = dataset months: [ 3, 5, 7, 9, 12, 14, 18, 2, 4, 6, 6, 8, 15, 1 ], died: [ 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1 ], arm: %w[ drug ] * 7 + %w[ placebo ] * 7 chart :survival, cohort, time: :months, event: :died, color: :arm
Table
Rows as a table, numbered like figures.
baseline = dataset arm: %w[ Drug Placebo ], n: [ 152, 149 ], age: [ 61.2, 60.8 ] table baseline, title: "Baseline", caption: "Mean age, by arm."
Every setting
In a block as title "…", or as a keyword: title: "…".
Words
title- Above the chart, bold
title "Patients seen" subtitle- Under the title
subtitle "Intention to treat" caption- Under the chart, after “Figure 1.”
caption "By month, 2024." source- Smallest, at the foot
source "Clinic records" numbered- Leave out “Figure 1.”
numbered false
Axes
x, y- Which column goes on each axis
x :week y [ … ]- A line or bar per column
y [ :sbp, :dbp ] label:- The axis title
y :sbp, label: "Systolic (mmHg)" format:- How numbers read
y format: :percent from:, to:- Where the axis starts and ends
y from: 0, to: 1 ticks:- Roughly how many marks
x ticks: 10 scale:- :linear, :log, :date or :band
x scale: :log log- Log scale on an axis
log :x x_label: …- Any axis setting, as a keyword
chart :line, d, y_label: "Mean"
Colour
color- One colour for everything
color :red color :column- A colour per value of a column
color :arm color … =>- Choose the colours
color :arm, "drug" => :red, "placebo" => :faint opacity- How solid fills are, 0 to 1
opacity 0.5
Marks on the chart
error- Error bars, or a band on a line
error low: :ci_low, high: :ci_high hline- A line across, at a value
hline 0.5, label: "Target" vline- A line up, at a value
vline 8, label: "Surgery" band- A shaded span
band x: 4..8, label: "Treatment" note- Words at a point
note 10, 0.7, "Plateau" trend- Least-squares line (scatter)
trend true
Look
legend- :top, :bottom, :right, :end or :none
legend :bottom aspect- Width over height
aspect 2 grid- Grid lines: false, true or :both
grid :both points- Dots on lines; values on boxes
points true width- Line width
width 2 dashed- Dashed lines
dashed true size- Point or square size, or a column
size :n stack- Stack bars or areas
stack true horizontal- Bars lying down
horizontal true labels- Values on the bars
labels true bins- Bars in a histogram
bins 20
Survival and forest
time, event- Follow-up, and whether the event happened
time :months; event :died logrank- Leave out the log-rank p
logrank false label- The row names in a forest plot
label :study reference- Line of no effect: 1 on log, 0 otherwise
reference false
Formats
:percent- 0.25 → 25%
:integer- 1234.6 → 1,235
:thousands- 12500 → 12,500
:decimal- two places
:scientific- 1.20e+04
"%.1f mg"- printf, any way you like
->(v) { … }- a lambda
Colours
:ink:red:green:blue:yellow:purple:orange:teal:soft:faint
Or any "#rrggbb".