Unit 03.05: Generate the mechanics, write the meaning
Half of a data dictionary can be generated in four lines. The half that makes it worth having cannot be generated at all.
Generate the mechanics, write the meaning
A data dictionary lists each column with its type, its missingness, an example value and โ the essential part โ what it actually means. Where the value came from, what it excludes, what a reader would wrongly assume.
The mechanical half is free: R already knows the names, the types, the NA counts. Generating that means it can never drift out of date with the data.
The meaning has to be written by someone who asked. Does recorded mean the date of the visit or the date of the submission? Does visits include cancellations? These questions are cheap to ask now and expensive to reconstruct later.
This block generates the mechanical columns and then adds the written one.
suppressPackageStartupMessages({library(dplyr); library(tibble)})
ward_visits <- tibble(
ward = c("North", "South", "East"),
visits = c(412, 388, 502),
recorded = as.Date(c("2026-01-31", "2026-01-31", "2026-01-31")),
staffed = c(TRUE, TRUE, FALSE)
)
# The mechanical half of a dictionary can be generated. Do that much for free.
dictionary <- tibble(
column = names(ward_visits),
type = sapply(ward_visits, function(x) class(x)[1]),
missing = sapply(ward_visits, function(x) sum(is.na(x))),
example = sapply(ward_visits, function(x) as.character(x[1]))
)
# The half that matters is written by a human and cannot be generated.
dictionary$meaning <- c(
"Ward name as recorded by the front desk; free text, not a code list",
"Count of completed visits; excludes cancellations",
"Date the return was submitted, not the date of the visits",
"TRUE if the ward met its minimum staffing on that date"
)
print(dictionary, width = Inf)
cat("\nThe 'meaning' column is why the file is useful. Nothing generates it.\n")
The generated table gives four columns with their types, zero missing values each, and an example. Then meaning is attached by hand, and it is the only column that resolves a real ambiguity โ recorded turns out to be the submission date, not the visit date, which changes how any time-based analysis must be read.
The mistake this prevents
The mistake is a dictionary that lists types and stops. It duplicates what glimpse() already prints and answers none of the questions a new analyst actually has.
Takeaway
Generate the type, missingness and example columns so they stay current. Write the meaning yourself, and record specifically what each column excludes.
