Variable Codebook Template (Statistics, Measurement Levels, R and Python)
Research question to variables, measurement levels, variable roles with a causal sketch, codebook table, Likert and reverse coding, R and Python codebook checks
使用方法: Use before collecting or analysing data to define every variable: level, role, unit, allowed values, missing codes and derived formulas. Fill the codebook row by row and run the R or Python check on each data export. Main pitfall: treating numeric codes as numbers and reversing items before recoding missing codes.
预览
Variable Codebook: [Your study question or course project]
A working codebook for your own project: it turns a research question into named variables, records the measurement level and role of each one, fixes the codes for answers and missing values, and checks a data file against those rules in R and Python. It is for students on a statistics or methods course, thesis writers preparing their data, and analysts who inherit a data set. It speeds up learning because every later choice (summary, chart, test, model) depends on the measurement level and role you record here, so you practise that decision once, carefully, and then reuse it. The worked examples use fictional data; replace them with your own. Source basis: Stevens (1946) on scales of measurement, the NIST/SEMATECH e-Handbook, and DDI codebook practice, written in original words.
Document control
| Field | Value |
|---|---|
| Course or project | [Course code and title, or thesis project name] |
| Learner or analyst | [Your name] |
| Data set | [Name of the data file and its export date, e.g. wellbeing_pilot_2026-03-14.csv] |
| Software and versions | R 4.5.1 (base and stats); Python 3.14 with pandas 3.1.0 and numpy 2.5.4 |
| Date | YYYY-MM-DD |
| Version | [0.1] |
What a codebook is for
A codebook is the dictionary of your data set. For every column it says what the column means, how it was measured, which values are allowed, how missing answers are coded, and where the column came from. Without one, two people reading the same file will make different assumptions: one will treat a code of 99 as a real age, another will treat "year of study" as a number to average, and a third will forget that question 3 of a scale was worded the other way round. Each of those slips changes results silently.
The codebook also forces two decisions that drive every later step of the analysis. The measurement level of a variable tells you which summaries and tests are meaningful (you cannot take the mean of faculty names). The role of a variable (outcome, predictor, covariate, confounder, mediator, moderator) tells you where it goes in the model. Students who record both decisions early find test selection much easier, because the test selector questions ("what type is the outcome? how many groups? are they paired?") are already answered on paper.
| Use this template when | Do not rely on it alone when |
|---|---|
| You are designing a survey, experiment or data extraction | The data come with an official codebook you must not change (use it, and add a local notes column) |
| You receive a data file with unclear column names or codes | Variables are free text that needs qualitative coding (use a coding frame for qualitative data) |
| You need to document a thesis data set for examiners or a replication package | You need a full metadata standard for an archive (follow the archive's DDI or schema requirements) |
From research question to variables
Start from one precise research question. A useful pattern is: "In [population], is [exposure or predictor] associated with [outcome], after accounting for [other factors]?" Then work in three steps.
- Concepts. Underline the abstract ideas in the question: "sleep", "stress", "academic performance".
- Operational definitions. For each concept, say exactly how you will measure it: "sleep = self-reported average hours per night over the past week", "stress = mean of four 5-point items", "performance = grade point average from the registry, 0 to 4".
- Variables. Give each measurement a short machine name (lowercase, no spaces, e.g.
sleep_h), a human label, a type and a unit. Add the variables you need for design and control: identifiers, group, time point, and the factors that could confound the relation you care about.
Fill in your own version below.
| Step | My answer |
|---|---|
| Research question (one sentence) | [In ... is ... associated with ... after accounting for ...?] |
| Concepts | [concept 1], [concept 2], [concept 3] |
| Operational definition of the outcome | [How exactly is it measured, by whom, on what scale?] |
| Operational definition of the main predictor | [ ] |
| Other factors to record (possible confounders, moderators) | [ ] |
| Design variables (ID, group, time, site) | [ ] |
| Example: research question | In Lakemoor University undergraduates, is average sleep associated with perceived stress, after accounting for faculty and year of study? |
Measurement levels and what each allows
Stevens (1946) proposed four levels of measurement. Each level keeps all the properties of the level below it and adds one more, so the list of meaningful operations grows as you go down the table.
| Level | What the numbers or labels mean | Meaningful operations | Typical summaries | Examples (Lakemoor University) |
|---|---|---|---|---|
| Nominal | Categories with no order | Equal or not equal, counting | Counts, proportions, mode | Faculty (ARTS, SCI, BUS, ENG), residence hall |
| Ordinal | Categories with an order, gaps not equal | Plus greater or less than | Median, percentiles, mode | Year of study (1 to 4), a single Likert item, class rank |
| Interval | Equal gaps, arbitrary zero | Plus addition and subtraction | Mean, SD, differences | Temperature in °C, calendar year, many standardised test scales |
| Ratio | Equal gaps and a true zero | Plus multiplication and ratios | Mean, SD, geometric mean, coefficient of variation | Sleep hours, age, library visits, income, reaction time |
A quick check for ratio level: does "twice as much" make sense? Eight hours of sleep is twice four hours, so sleep is ratio. 20 °C is not "twice as warm" as 10 °C, because 0 °C is not "no temperature", so Celsius is interval. Kelvin, with a true zero, is ratio.
Two further distinctions help when you choose methods. A variable is discrete if it takes separate values (counts such as visits per week) and continuous if any value in a range is possible (time, weight). A nominal variable with exactly two categories is binary (dichotomous), and many methods treat binary variables specially (proportions, logistic regression).
The levels are a guide, not a law. Velleman and Wilkinson (1993) argued that applying the levels as strict rules can mislead: a sum of ten Likert items is often analysed as interval with good results, and some ordinal data carry more information than the label suggests. The practical rule is: record the level honestly in the codebook, and when you treat a variable as a higher level than it strictly is (for example, the mean of a multi-item scale), write down that you are doing so and why.
Variable roles in the analysis
The role of a variable is not a property of the variable; it depends on the question. Sleep can be an outcome in one study and a predictor in the next. For your main question, assign each variable one role.
| Role | Plain meaning | What to do with it | Lakemoor example |
|---|---|---|---|
| Outcome (dependent variable, response) | The thing you want to explain or predict | Left-hand side of the model | Perceived stress score |
| Predictor (exposure, independent variable, treatment) | The variable whose effect or association you study | Main right-hand side term | Average sleep hours |
| Covariate | Another variable in the model, often to improve precision | Include if it predicts the outcome | Age |
| Confounder | A common cause of predictor and outcome; it creates a false or distorted association | Adjust for it (in the design or the model) | Faculty: heavy lab timetables shorten sleep and raise stress |
| Mediator | A variable on the path from predictor to outcome | Do not adjust for it if you want the total effect | Daytime tiredness (sleep lowers tiredness, tiredness raises stress) |
| Moderator (effect modifier) | A variable that changes the size or direction of the predictor's effect | Add an interaction term or analyse subgroups | Paid work hours: the sleep and stress relation may be stronger for students who work |
A causal sketch makes these roles visible. In a directed acyclic graph (DAG), each arrow means "is assumed to cause". The sketch below is not a result; it is an assumption you write down so readers can disagree with it.
How to read it: faculty points to both sleep and stress, so it opens a "back door" path between them and must be
adjusted for. Tiredness lies on the path from sleep to stress, so adjusting for it would remove part of the effect
you want to measure. Paid work hours is drawn with dotted lines because a moderator changes the strength of an
arrow rather than causing a variable; in a model it becomes the interaction sleep_h:work_h. Age only points to the
outcome, so including it can sharpen precision but does not remove bias. Strictly, a formal DAG has no "effect
strength" node; the dotted part is a teaching shortcut for moderation.
Codebook table
| Name | Label | Level | Role | Unit | Allowed values | Missing codes | Source | Derived from |
|---|---|---|---|---|---|---|---|---|
| Example: id | Respondent identifier | Nominal | Design (ID) | none | 1 to 9999, unique | none allowed | Survey platform | |
| Example: faculty | Faculty of enrolment | Nominal | Confounder | none | ARTS, SCI, BUS, ENG | blank = not answered | Registry | |
| Example: year | Year of study | Ordinal | Covariate | year | 1, 2, 3, 4 | blank = not answered | Registry | |
| Example: sleep_h | Average sleep per night, past 7 days | Ratio | Predictor | hours | 0 to 12 | -9 = refused | Survey Q5 | |
| Example: q1 | "I felt unable to control important things" | Ordinal | Scale item | 1 to 5 | 1 = never ... 5 = very often | -9 = refused | Survey Q6a | |
| Example: q3_rev | "I felt on top of things" (positively worded) | Ordinal | Scale item | 1 to 5 | 1 = never ... 5 = very often | -9 = refused | Survey Q6c | |
| Example: q3 | q3_rev reverse coded | Ordinal | Scale item | 1 to 5 | 1 to 5 | NA | Script step 3 | 6 - q3_rev |
| Example: stress | Perceived stress score | Interval (treated) | Outcome | points, 1 to 5 | 1.00 to 5.00 | NA if any item missing | Script step 4 | mean(q1, q2, q3, q4) |
| [name] | [label] | [level] | [role] | [unit] | [values or range] | [codes and meaning] | [source] | [formula or blank] |
| [name] | [label] | [level] | [role] | [unit] | [values or range] | [codes and meaning] | [source] | [formula or blank] |
Rules that save time later:
- Names. Lowercase letters, digits and underscores; start with a letter; keep them short but readable
(
sleep_h, notQ5_SleepHoursAvgPastWeek). Suffix reversed items (_rev) and derived scores clearly. - Codes for categories. Use stable short codes in the data and keep the wording in the codebook. Never reuse a code for a different meaning between survey waves.
- Missing codes. Distinguish reasons when they matter: for example
-9refused,-8don't know,-7not applicable (skipped by routing). Choose codes that cannot be real values. Never use 0 or 99 for an age or a count. - Units. State the unit for every number, including time windows ("per week", "past 7 days").
- Derived variables. Write the exact formula and the rule for missing items. A derived variable is never typed in by hand.
Coding Likert items and reverse coding
A Likert item is one statement with ordered answer options, such as 1 = never, 2 = almost never, 3 = sometimes, 4 = fairly often, 5 = very often (Likert 1932). Each single item is ordinal. A scale combines several items about the same concept into one score, usually the sum or the mean. Scale scores have more possible values and are often analysed as interval, which is a convention you should state, not a fact.
Questionnaires often include some positively worded items to stop people from ticking the same column every time. For "I felt on top of things", a high answer means low stress, so the item must be flipped before it is combined with the others. The plain rule: the lowest code becomes the highest and vice versa. As a formula, for an item with smallest code and largest code :
| Symbol | Meaning |
|---|---|
| the original code given by the respondent | |
| , | the smallest and largest possible codes of the item (not the observed ones) |
| the code after reversing |
For a 1 to 5 item, , so 1 becomes 5, 2 becomes 4, 3 stays 3. For a 0 to 4 item, , so 0 becomes 4. Using on a 0 to 4 item is a classic error: 0 would become 6, which is not a valid code.
Three habits make Likert coding safe. First, recode missing codes to NA before reversing, otherwise
becomes on a 1 to 5 item and looks like a valid extreme score. Second, keep the original column and create the
reversed one under a new name, so the step is visible and can be checked. Third, after building a scale, check that
all items correlate positively with each other; a negative correlation usually means an item that should have been
reversed was not (see academic/stats-reliability-factor-analysis for Cronbach's alpha and item analysis).
The chart shows the counts of item q3 in the worked example before and after reversing. The shape is mirrored, which is exactly what reversing should do: the bars swap ends, and the middle category stays where it is.
Worked example A: checking a data file against the codebook
Setting. A pilot survey of ten Lakemoor University students (fictional) records faculty, year of study, average
sleep hours and four stress items. Item q3 is positively worded and stored as q3_rev. The codebook allows faculty
codes ARTS, SCI, BUS and ENG only, years 1 to 4, sleep 0 to 12 hours, item codes 1 to 5, and uses for refused.
Step 1: make the codebook machine-readable. Put the name, level, minimum, maximum, allowed codes and missing code of each variable into a small table inside the script. This is the same information as the codebook table, in a form the computer can loop over.
Step 2: check every variable. For each variable, a value is a problem if it is not a missing code and it is either outside the allowed list (categorical variables) or outside the range (numeric variables).
# Lakemoor University wellbeing pilot (fictional)
d <- data.frame(
id = 1:10,
faculty = c("ARTS","SCI","SCI","BUS","ARTS","ENG","SCI","BUS","ARTS","LAW"),
year = c(1, 2, 2, 3, 1, 4, 5, 2, 3, 1),
sleep_h = c(7.5, 6.0, 8.0, 5.5, -9, 7.0, 6.5, 14.0, 7.0, 6.0),
q1 = c(4, 2, 3, 5, 4, 1, 3, 4, 2, 3),
q2 = c(4, 1, 3, 5, 5, 2, 3, 4, 2, 6),
q3_rev = c(2, 5, 3, 1, 1, 4, 3, 2, 4, 3),
q4 = c(5, 2, 2, 4, 4, 1, 3, -9, 2, 3)
)
cb <- data.frame(
name = c("faculty","year","sleep_h","q1","q2","q3_rev","q4"),
type = c("nominal","ordinal","ratio","ordinal","ordinal","ordinal","ordinal"),
min = c(NA, 1, 0, 1, 1, 1, 1),
max = c(NA, 4, 12, 5, 5, 5, 5),
allowed = c("ARTS,SCI,BUS,ENG", NA, NA, NA, NA, NA, NA),
missing = c(NA, NA, -9, -9, -9, -9, -9)
)
problems <- data.frame()
for (i in seq_len(nrow(cb))) {
v <- cb$name[i]; x <- d[[v]]
miss <- !is.na(cb$missing[i]) & x %in% cb$missing[i]
if (!is.na(cb$allowed[i])) {
ok <- x %in% strsplit(cb$allowed[i], ",")[[1]]
} else {
ok <- x >= cb$min[i] & x <= cb$max[i]
}
bad <- which(!ok & !miss)
if (length(bad)) problems <- rbind(problems,
data.frame(variable = v, id = d$id[bad], value = x[bad]))
}
print(problems, row.names = FALSE)
# Recode missing codes to NA, then reverse-code q3 on a 1-5 scale
for (v in cb$name[!is.na(cb$missing)]) d[[v]][d[[v]] == -9] <- NA
d$q3 <- 6 - d$q3_rev
d$stress <- rowMeans(d[, c("q1","q2","q3","q4")])
print(d[1:4, c("id","q3_rev","q3","stress")], row.names = FALSE)
variable id value
faculty 10 LAW
year 7 5
sleep_h 8 14
q2 10 6
id q3_rev q3 stress
1 2 4 4.25
2 5 1 1.50
3 3 3 2.75
4 1 5 4.75
import numpy as np, pandas as pd
d = pd.DataFrame({
"id": range(1, 11),
"faculty": ["ARTS","SCI","SCI","BUS","ARTS","ENG","SCI","BUS","ARTS","LAW"],
"year": [1, 2, 2, 3, 1, 4, 5, 2, 3, 1],
"sleep_h": [7.5, 6.0, 8.0, 5.5, -9, 7.0, 6.5, 14.0, 7.0, 6.0],
"q1": [4, 2, 3, 5, 4, 1, 3, 4, 2, 3],
"q2": [4, 1, 3, 5, 5, 2, 3, 4, 2, 6],
"q3_rev": [2, 5, 3, 1, 1, 4, 3, 2, 4, 3],
"q4": [5, 2, 2, 4, 4, 1, 3, -9, 2, 3],
})
cb = pd.DataFrame({
"name": ["faculty","year","sleep_h","q1","q2","q3_rev","q4"],
"type": ["nominal","ordinal","ratio","ordinal","ordinal","ordinal","ordinal"],
"min": [np.nan, 1, 0, 1, 1, 1, 1],
"max": [np.nan, 4, 12, 5, 5, 5, 5],
"allowed": ["ARTS,SCI,BUS,ENG", None, None, None, None, None, None],
"missing": [np.nan, np.nan, -9, -9, -9, -9, -9],
})
rows = []
for r in cb.itertuples():
x = d[r.name]
miss = x.eq(r.missing) if not np.isnan(r.missing) else pd.Series(False, index=x.index)
ok = x.isin(r.allowed.split(",")) if isinstance(r.allowed, str) else x.between(r.min, r.max)
for i in d.index[~ok & ~miss]:
rows.append((r.name, d.at[i, "id"], x[i]))
print(pd.DataFrame(rows, columns=["variable", "id", "value"]).to_string(index=False))
for v in cb.loc[cb["missing"].notna(), "name"]:
d[v] = d[v].replace(-9, np.nan)
d["q3"] = 6 - d["q3_rev"]
d["stress"] = d[["q1","q2","q3","q4"]].mean(axis=1, skipna=False)
print(d.loc[:3, ["id","q3_rev","q3","stress"]].to_string(index=False))
variable id value
faculty 10 LAW
year 7 5
sleep_h 8 14.0
q2 10 6
id q3_rev q3 stress
1 2 4 4.25
2 5 1 1.50
3 3 3 2.75
4 1 5 4.75
Step 3: read the problem list. Both languages find the same four problems, and none of them is a missing code:
| Variable | ID | Value | Diagnosis | Action (record it in the cleaning log) |
|---|---|---|---|---|
| faculty | 10 | LAW | Code not in codebook: either a new faculty or a typo | Ask the data owner; if LAW is real, add it to the codebook with a revision entry |
| year | 7 | 5 | Out of range 1 to 4 | Check registry; fifth-year students may exist (update codebook) or it is an entry error |
| sleep_h | 8 | 14 | Above the 12-hour maximum | Implausible as a weekly average; set to NA with a logged reason, never silently |
| q2 | 10 | 6 | Not a valid code on a 1 to 5 item | Set to NA; check the survey export for a shifted code |
Note that the values for id 5 (sleep) and id 8 (q4) are not listed, because the codebook says they are legitimate missing codes. That is the point of writing them down.
Step 4: check the derived variables by hand. For respondent 1, the raw items are q1 = 4, q2 = 4, q3_rev = 2, q4 = 5. Reversing gives q3 = 6 − 2 = 4. The stress score is , matching the output. For respondent 2: q3 = 6 − 5 = 1, score . A hand check of two rows catches most formula errors.
A difference between R and Python worth knowing. rowMeans() in R returns NA for a row with any missing item
unless you add na.rm = TRUE. pandas mean() does the opposite: it skips missing values by default, so the code
sets skipna=False on purpose. With the default, respondent 8 (q4 missing) would silently get a stress score from
three items in Python but NA in R. The codebook's "missing rule" column ("NA if any item missing") is what decides
which behaviour you want, and the code must say it explicitly.
Interpretation. The data file is not ready for analysis: four values break the codebook. The codebook did its job by turning a ten-row eyeball check into a four-line problem list. For a 2,000-row file the gain is far larger.
Worked example B: Brightwell Bakery quality survey (half solved)
Setting. Brightwell Bakery (fictional) records, for each batch of loaves: the oven used (Oven A, B or C), the oven temperature in °C, the loaf weight in grams, the number of loaves rejected, a taster's rating "poor, fair, good, excellent", and the item "The crust was too hard" on a 1 to 5 agreement scale, where all other taste items are positively worded. The question is: "Does oven temperature affect loaf weight, allowing for which oven is used?"
| Name | Label | Level | Role | Allowed values | Missing code | Note |
|---|---|---|---|---|---|---|
| oven | Oven used | Nominal | Covariate (or confounder) | A, B, C | blank | Labels, no order |
| temp_c | Oven temperature | [ ] | Predictor | 150 to 260 | -9 | [Why not ratio?] |
| weight_g | Loaf weight | Ratio | [ ] | 300 to 1,200 | -9 | True zero; "twice as heavy" is meaningful |
| rejects | Loaves rejected per batch | [ ] | Secondary outcome | 0 to 50 | -9 | [Discrete or continuous?] |
| rating | Taster rating | [ ] | Secondary outcome | 1 = poor ... 4 = excellent | -9 | Order but unequal gaps |
| crust_rev | "The crust was too hard" | Ordinal | Scale item | 1 to 5 | -9 | Reverse with [ ] |
Gaps to complete: (1) level of temp_c and the reason; (2) role of weight_g; (3) level of rejects and whether it
is discrete; (4) level of rating; (5) the reverse-coding formula for crust_rev; (6) a reverse-coded value of 2
becomes [ ].
Exercise C: Harbour City Library opening hours
Harbour City Library (fictional) extended opening hours at two of its four branches in March. The analyst wants to
know: "Did longer opening hours increase daily visits, taking day of the week and rainfall into account?" The daily
file has: branch (Central, North, East, West), date, day (Mon to Sun), open_h (hours open that day),
visits (door counter), rain_mm (rainfall that day), extended (1 if the branch has the new hours, 0 if not),
and counter_fault (1 if the door counter was broken for part of the day).
Tasks: (a) give the level and role of each variable; (b) write a full codebook row for visits including a missing
code strategy for days when the counter was broken; (c) name one possible confounder that is not in the file and
draw it into a causal sketch (arrows in words are fine).
Codebook quality checklist
- Every column in the data file has exactly one codebook row, and every codebook row exists in the data.
- Each row has a level, a role for the main question, a unit and allowed values.
- Missing codes are listed, cannot be confused with real values, and distinguish reasons where it matters.
- Reversed items are flagged from their wording, with the formula and the item range.
- Every derived variable has a formula and a missing-item rule, and is created by script.
- The causal sketch is drawn, and the adjustment set (confounders) is written next to it.
- The checking script runs on the current data export and its output is saved in the cleaning log.
- The codebook version and date match the analysis that uses it.
Common mistakes and misconceptions
| Mistake or misconception | Why it is wrong | Correct practice |
|---|---|---|
| "Numbers in the column, so it is a numeric variable." | Faculty coded 1 to 4 is still nominal; the mean faculty 2.4 has no meaning. | Classify by what the codes mean, not by the storage type. Store such codes as factors or categories. |
| Averaging a single Likert item and calling it interval | One item has five ordered labels with unknown gaps. | Report the median and the distribution for a single item; reserve means for multi-item scales and say so. |
| Treating 99 or 0 as a valid answer | A missing code that looks like a real value enters every mean. | Use impossible codes (such as −9) and convert them to NA before any analysis. |
| Reversing before recoding missing codes | −9 reversed on a 1 to 5 item becomes 15. | Recode missing to NA first, then reverse. |
| Using for every scale | Correct only for items coded 1 to 5. | Use with the item's own minimum and maximum. |
| "Adjust for everything that is measured." | Adjusting for a mediator removes part of the effect; adjusting for a collider (a common effect) can create bias. | Choose the adjustment set from the causal sketch, not from the column list. |
| "Moderator and mediator are the same thing." | A mediator carries the effect; a moderator changes its size. | Mediator: on the arrow path. Moderator: an interaction term. |
| Editing values in the spreadsheet by hand | No record of what changed and why; not reproducible. | Change values only in a script and log each rule (see academic/stats-data-cleaning-log). |
Self-test questions
- A survey records "household income band: under 20k, 20k to 40k, 40k to 60k, over 60k". What is the level, and is the mean band a sensible summary?
- Why is temperature in °C interval and not ratio? Give one statement that is meaningful and one that is not.
- A 7-point item runs from 1 to 7. Reverse-code the answer 2. Then do the same for a 0 to 6 item answered 2.
- In a study of exercise and exam scores, motivation causes both more exercise and higher scores. What role does motivation play, and what happens if you leave it out of the model?
- In the same study, exercise improves sleep, and sleep improves exam scores. Should sleep be adjusted for when the aim is the total effect of exercise? Why?
- In worked example A, why does respondent 5's sleep value of −9 not appear in the problem list?
My notes and next steps
| Item | My entry |
|---|---|
| Confidence with measurement levels (1 to 5) | [ ] |
| Confidence with variable roles and causal sketches (1 to 5) | [ ] |
| Questions still open | [ ] |
| Mistakes to copy into my error log (academic/stats-error-log) | [ ] |
| Next step | [Run the checking script on my data, then start academic/stats-data-cleaning-log] |
| Review again on | YYYY-MM-DD (about one week from today, then one month) |
Sources and further reading
Structure aligned with common codebook practice (variable name, label, type, values, missing codes, provenance) as described by the Data Documentation Initiative, and based on the classic measurement-level framework.
- Stevens, S. S. (1946). On the theory of scales of measurement. Science, 103(2684), 677–680.
- Velleman, P. F., and Wilkinson, L. (1993). Nominal, ordinal, interval, and ratio typologies are misleading. The American Statistician, 47(1), 65–72.
- Likert, R. (1932). A technique for the measurement of attitudes. Archives of Psychology, 140, 1–55.
- Baron, R. M., and Kenny, D. A. (1986). The moderator-mediator variable distinction in social psychological research: conceptual, strategic, and statistical considerations. Journal of Personality and Social Psychology, 51(6), 1173–1182.
- Hernán, M. A., and Robins, J. M. (2020). Causal Inference: What If. Chapman and Hall/CRC (causal diagrams, confounding, colliders).
- Pearl, J. (2009). Causality (2nd ed.). Cambridge University Press.
- NIST/SEMATECH e-Handbook of Statistical Methods, chapter 1 Exploratory Data Analysis, https://www.itl.nist.gov/div898/handbook/ (accessed 2026-10-25). Public domain.
- Data Documentation Initiative (DDI Alliance): metadata standard for describing survey and research data (name only).
- Further reading: de Smith, M. J., Statistical Analysis Handbook (2024 edition, statsref.com); Diez, Çetinkaya-Rundel and Barr, OpenIntro Statistics (chapter on data basics).
Answer key
Worked example B.
(1) temp_c is interval: equal gaps, but 0 °C is not "no heat", so 200 °C is not twice as hot as 100 °C.
(2) weight_g is the outcome. (3) rejects is ratio (a count with a true zero) and discrete.
(4) rating is ordinal. (5) . (6) A value of 2 becomes 4.
Exercise C.
(a) branch: nominal, design variable (and possible confounder, since the extended branches were chosen, not
randomised). date: interval (time), design variable for trends. day: ordinal by calendar order but usually
treated as nominal in models (weekday effects are not equally spaced); covariate. open_h: ratio, mechanism of the
intervention. visits: ratio count, discrete, outcome. rain_mm: ratio, covariate. extended: nominal binary,
main predictor. counter_fault: nominal binary, data-quality flag.
(b) Example row: visits | Door-counter visits per branch per day | Ratio (count) | Outcome | visits per day |
0 to 5,000 | NA when counter_fault = 1 (counts are partial and not comparable) | Door counter export | none.
(c) For example, branch size or neighbourhood footfall: busier branches may have been picked for extended hours and
also have more visits. Sketch: footfall → extended; footfall → visits; extended → visits.
Self-test.
- Ordinal (ordered bands, unequal or open-ended widths). The mean band is not sensible; report the median band and the percentage in each band.
- 0 °C is an arbitrary zero. Meaningful: "20 °C is 10 degrees warmer than 10 °C". Not meaningful: "20 °C is twice as warm as 10 °C".
- 1 to 7: . 0 to 6: .
- Motivation is a confounder (common cause). Leaving it out biases the exercise coefficient, here probably upward, because part of the motivation effect is credited to exercise.
- No. Sleep is a mediator on the path exercise → sleep → scores; adjusting for it estimates only the direct effect and removes part of the total effect.
- Because −9 is listed as a missing code for
sleep_h, the check treats it as a legitimate missing value, not as an out-of-range number. It becomes NA in the recoding step.
Revision history
| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [Your name] | First draft from the research question |
| 0.2 | YYYY-MM-DD | [Your name] | Example: Added LAW to faculty codes after registry check; year range now 1 to 5 |
| 1.0 | YYYY-MM-DD | [Your name] | Frozen before main analysis |
相关模板
Statistical Analysis Plan Template (Statistics, Thesis or Project)
Statistical analysis plan for a thesis or project: estimands, hypotheses, sample size, primary model, pre-set assumption fallbacks, missing data, multiplicity, sensitivity, deviations log
学术Statistical Analysis Report Template (Statistics, Thesis or Client)
Complete statistical analysis report for a thesis results chapter or client: plain-language summary, methods, descriptives, main analyses, assumption checks, sensitivity, limitations, reproducibility appendix, reviewer checklist
学术ANCOVA Method Card Template (Statistics, R and Python)
Analysis of covariance: covariate adjustment, homogeneity of slopes, adjusted means by hand and with emmeans, ANCOVA vs change scores, Lord's paradox, reporting