Analytic Codebooks

A shared documentation standard for PSY 652 projects

What a codebook does

A codebook is the map of the dataset you actually analyze. It tells another researcher what each variable means, how it is represented in R, what counts as missing, where it came from, and whether you changed it.

For PSY 652, every group project uses the same small analytic-codebook format. The goal is not to document every column in a large raw file. The goal is to make the analytic dataset understandable without forcing a reader to open the code and reverse-engineer it.

A word before the details. Writing a codebook is the least glamorous part of a project and one of the most useful — it is the file that lets a reader, a teammate, or you-in-three-weeks understand what a column actually contains. It is also genuinely fiddly the first time: you will not be sure how much detail to put in values, or how to phrase a derivation that took four lines of code. That uncertainty is normal, and it resolves quickly once you have written a few rows. If you are stuck on how to document something, bring the variable to lab and we will work through it together — it is a much faster conversation in person than in writing.

The PSY 652 convention

Create one file:

documentation/codebook.csv

It documents the variables in your final analytic dataset — the variables that enter a table, figure, descriptive calculation, hypothesis test, or another required part of the analysis.

Use these seven columns, in this order:

Column What belongs there
variable Exact variable name in your analytic dataset
description Plain-language meaning of the variable
type How the variable is represented in R
values Categories, coding, units, or observed/theoretical range
missing What NA means and any structural missingness or special missing-data rule
source Raw variable(s) from which this variable came
derivation What you did to turn the source variable(s) into this analytic variable

These seven fields are enough to answer the questions a future analyst usually has first:

What is this? What values can it take? What does missing mean? Where did it come from? Did you change it?


What belongs in the codebook?

Document a variable if it enters the analysis.

That usually includes:

  • participant or case identifiers used to check or organize the data,
  • focal outcomes,
  • grouping variables,
  • variables used in Table 1,
  • survey weights if you use them,
  • variables used to define exclusions or the analytic sample,
  • variables shown in a figure,
  • and derived variables created with mutate() or another transformation.

You do not need to document hundreds of unused columns that happen to exist in the raw file. A focused codebook is easier to write, easier to read, and usually more useful.

Raw codebook versus analytic codebook

The organization that collected the data may already provide a large raw-data codebook. Keep it with the source documentation — it remains the authoritative reference for the original file.

Your PSY 652 codebook serves a different purpose. It documents the small set of variables that survived into your analysis, including the recoding and derivation decisions the original codebook cannot know about.


The seven columns, carefully

variable

Use the exact name that appears in the analytic data frame.

Good:

age_group
mde_pastyear
wtp
condition

Not:

Age group variable
Depression
The outcome

A reader should be able to copy the name from the codebook and find the same column in glimpse(analytic).

description

Write a concise definition in ordinary language.

Good:

Past-year major depressive episode indicator

Willingness to pay for the special boulder, in Ice Dollars

Avoid merely translating the variable name:

MDE past year

For a survey item, summarize what was measured. The full question wording can remain in the original questionnaire unless the wording itself is crucial to interpretation.

type

Describe the analytic representation in R, not merely the raw storage format.

Use a small vocabulary:

  • numeric
  • integer
  • factor
  • ordered factor
  • logical
  • character
  • date

For example, a survey variable may have arrived from SPSS as <dbl+lbl> but become a factor before analysis. The codebook should say factor, because that is the variable the analysis uses.

values

For categorical variables, list the analytic categories in their meaningful order:

No; Yes
18–29; 30–49; 50–64; 65+
Control; Treatment

For numeric variables, give the units and meaningful range when known:

0–10; higher = greater interference
0–250 Ice Dollars
Proportion from 0 to 1
Survey weight; positive numeric

Do not paste a long frequency table here. Frequencies belong in the analysis, not the codebook.

missing

This column deserves care. NA does not always mean the same thing.

Examples:

None expected
DK/refused recoded to NA
Not asked of respondents who reported no social-media use
Missing if fewer than 3 of 4 items were answered
Original file uses blank/NA for item nonresponse

Distinguish structural missingness from ordinary item nonresponse whenever it matters.

Good:

Structurally missing for non-users because the item was not asked

Less useful:

NA = missing

source

Name the raw variable or variables from which the analytic variable came.

Examples:

F_AGECAT
SNSUSE_W163
wtp_final
severity_chores; severity_work; severity_family; severity_social

If the variable entered the analytic dataset unchanged, the source may simply be the same raw name.

This field is especially important in Project 2: it creates the auditable link between the published paper, the shared data file, and your analysis.

derivation

State briefly what you changed.

Useful phrases include:

Unchanged
Renamed only
Converted labelled values to factor; 99 = Refused recoded to NA
1 = Yes and 2 = No recoded to No/Yes factor
Reverse-coded from 1–4 so higher values indicate greater importance
Mean of items A–C among respondents with all 3 observed
Calculated as number_pills / population

The codebook does not replace the R code. It explains the transformation well enough that the reader knows what code to look for and what it was intended to accomplish.


Three common kinds of variables

1 · Variable used essentially as received

variable,description,type,values,missing,source,derivation
wtp,Willingness to pay for the special boulder,numeric,0–250 Ice Dollars,None expected,wtp_final,Renamed only

2 · Recoded categorical variable

variable,description,type,values,missing,source,derivation
any_social_media,Uses social media sites,factor,No; Yes,DK/refused recoded to NA,SNSUSE_W163,1 = Yes and 2 = No recoded to No/Yes factor

3 · Derived variable

variable,description,type,values,missing,source,derivation
age_group,Respondent age group,factor,18–29; 30–49; 50–64; 65+,Refused recoded to NA,F_AGECAT,Converted Pew value labels to factor levels

A more complex derived variable might look like:

variable,description,type,values,missing,source,derivation
severity_scale,Mean interference across four life domains,numeric,0–10; higher = more interference,Missing when the minimum-items scoring rule is not met,severity_chores; severity_work; severity_family; severity_social,Row mean of the four severity items; see the documented scoring rule

Start from this template

Create documentation/codebook.csv with this header:

variable,description,type,values,missing,source,derivation

Then add one row per analytic variable.

A small project might have only 8–15 rows. That is fine. A concise codebook that accurately documents the analysis is much more useful than a 500-row file nobody reads.


Render the codebook inside your Quarto report

Your CSV is the documentation source. Your .qmd can read the same file and render it as a polished table:

library(tidyverse)
library(here)
library(gt)

codebook <- read_csv(here("documentation", "codebook.csv"), show_col_types = FALSE)

codebook |>
  gt() |>
  tab_header(title = "Analytic Codebook")

Here is that code run against a real codebook — the one published for blorg_exp1 on the Course Datasets page

NoteWhy this example has five columns and yours has seven

Look closely and you’ll see the table below is missing source and derivation. That is deliberate, and the reason is worth understanding.

You receive the course datasets already prepared. The raw download, the recoding, and the filtering all happened in scripts you never run. So a course codebook only has to answer what is this variable?

Your project data is different: you are the one who prepares it. You download a raw file and build the analytic file yourself, which means nobody reading your project can reconstruct that step from the data alone. source and derivation are where you record it — and for your project they are the two most important columns in the table, because they are the only ones that document work you personally did.

So use the five columns below as the model for how to write a description, a values entry, and a missing entry. Then add source and derivation on top.

Analytic Codebook
blorg_exp1 — Hofman et al. (2020), Experiment 1
variable description type values missing
worker_id Anonymized Amazon Mechanical Turk worker identifier. The MTurk worker ID was hashed, so it identifies a participant without revealing the account. character 1,743 unique values None
condition.f Four-level experimental condition crossing visualization format and caption text factor 1: CI with viz stats only; 2: CI with extra info; 3: PI with viz stats only; 4: PI with extra info None
interval_CI Visualization format shown to the participant numeric 0 = PI; 1 = CI None
text_extra Whether the caption supplied information beyond the visualization numeric 0 = matching text; 1 = extra information None
wtp_final Willingness to pay to rent the special boulder, in Ice Dollars numeric Observed range: 0–249 Ice Dollars; instrument slider: 0–250 None
superiority Participant's estimate of the probability that the special boulder out-slides the standard one. Collected on a 0–100 scale and rescaled to a 0–1 proportion. Not used in the M09 lab — included so you can explore it yourself. numeric 0 to 1 None

This pattern has two advantages:

  1. the repository contains a simple machine-readable codebook that can be opened in any spreadsheet or text editor; and
  2. the report always displays the same documentation file rather than a separately maintained copy.

How the codebook relates to the rest of the project

The codebook answers what the variables are.

Other project documents answer different questions:

Document Its job
README.md What is this project, and how do I reproduce it?
data-provenance.md Where did the data come from, and how do I obtain them?
codebook.csv What does each analytic variable mean, and how was it constructed?
Project 1 plan What descriptive question are we answering?
Project 2 reproduction plan Which published result are we reproducing, and what exact analysis does it require?
.qmd report What did we do, what did we find, and what does it mean?

Avoid making one file do all six jobs.


Project 1 example

Suppose your Pew analysis asks how social-media use varies by age. Part of the codebook might look like:

variable description type values missing source derivation
any_social_media Uses social media sites factor No; Yes DK/refused → NA SNSUSE_W163 Recode 1 = Yes; 2 = No
age_group Respondent age group factor 18–29; 30–49; 50–64; 65+ Refused → NA F_AGECAT Convert labelled values to factor
WEIGHT_W163 Wave-specific survey weight numeric Positive numeric None expected WEIGHT_W163 Unchanged

Notice what is not in the codebook: whether age_group appears on the x-axis or whether any_social_media is the grouping variable. Those are analysis decisions explained in the report.


Project 2 example

Suppose a paper reports a two-sample t-test comparing CI and PI visualization conditions.

variable description type values missing source derivation
worker_id Anonymized participant identifier character Unique ID None expected worker_id Unchanged
condition Visualization condition used in target contrast factor PI; CI None after target-sample filter condition.f Filtered to target conditions and releveled
wtp Willingness to pay for special boulder numeric 0–250 Ice Dollars Rows with missing WTP excluded as specified by paper wtp_final Renamed only

The reproduction plan then explains that wtp is the continuous outcome and condition defines two independent groups. Keeping those roles outside the codebook lets the same codebook remain a description of the data rather than of one particular statistical command.


Codebook quality check

Before submission, another teammate should be able to open codebook.csv and answer all of these without reading your R code:

  • What does each analytic variable mean?
  • Which variables are categorical versus numeric?
  • What values or categories are possible?
  • What does NA mean for each variable where missingness matters?
  • Which raw variable(s) produced each analytic variable?
  • Which variables were recoded, renamed, or calculated?
  • Could I find the corresponding transformation in the .qmd?

If any answer is no, improve the codebook.

Let the data tell you its properties

There is a division of labor in this file that is worth naming, because getting it backwards is the most common source of codebooks that are confidently wrong.

Some columns describe facts R already knows. A variable’s type, its observed range or set of categories, and how much of it is missing are all properties of the analytic dataset sitting in front of you. Do not fill these in from memory, and do not copy them from the raw codebook — the raw codebook describes the file before your filters, recodes, and exclusions, so its ranges and categories may no longer be true of yours. Look instead:

To fill in Ask the data
type glimpse() — it prints the storage type of every column
values, for a categorical variable count() — the levels that actually occur, and how often
values, for a numeric variable range(), or summary() for the quartiles too
missing sum(is.na(x)), and count() if missingness is coded as a category

A five-second check beats a confident guess, and it catches the errors that matter most: a factor level you thought you had dropped, a 99 that never got recoded, a numeric column silently read in as character.

The other columns carry things R cannot know. No function will tell you what a variable means, why a value is missing, which raw column it came from, or what decision produced it. That is the part only you can write, and it is the part a reader actually needs.

Compute the properties; curate the meaning.

The standard to remember

A good codebook is not long. It is traceable.

A reader should be able to move:

meaning → analytic variable → raw source → documented transformation

without guessing.