Playground: Chapter 19
Putting It All Together
This page practises the ideas of Chapter 19 in four parts. Practise the chapter works through the book’s exercises, with starter code, hints, and solutions. Go further goes beyond the book, with new questions about reporting and choosing methods. Check your understanding asks short questions whose answers open with a click. Do it yourself gives open tasks with no answers, ending with a capstone: a research question of your own, carried from hypothesis to limitation.
The main practice for this chapter is the complete thesis project in the download project: from the raw survey export, through a cleaning script and an analysis script, to a results chapter written in Quarto. This page practises the pieces that make a results chapter, which run in the browser: helper functions for reporting, the sample table, sentences with numbers taken from models, and the chain of reasoning. In the exercises, replace each ______ with your own code and press Run Code.
In the setup, study has one row per student with the background variables, the stress and support scores, and the first-semester records, as in the chapter, and the chapter’s helpers mean_sd(), percent(), format_p(), and describe() are defined.
Practise the chapter
These are the exercises at the end of Chapter 19, with the same numbers.
Exercise 1: Run the whole project
Download the Chapter 19 project, run scripts/01_clean_data.py and scripts/02_analysis.py, and render results.qmd. Then change one cleaning rule (for example, treat ages above 70 as impossible), render again, and note which numbers change.
This exercise needs the project on your own computer, so it is done in the download project; its exercises.txt walks through the steps.
In scripts/01_clean_data.py, the rule for impossible ages becomes, for example:
responses.loc[(responses["age"] < 18) | (responses["age"] > 70), "age"] = np.nanAfter running both scripts and rendering again, only the numbers that involve age change: the mean age in the sample table, and the number of students with a known age. The models do not use age, so their coefficients, intervals, and p-values, and every sentence built from them, stay exactly the same. That is the point of the exercise: in a project where every number comes from code, a changed decision flows through to every result it affects, and to nothing else, without anyone retyping a number.
Exercise 2: Students with children in Table 1
Add a row to the sample table for the share of students with children, and build the table by programme.
The share of a yes-or-no condition, formatted as a percentage, is produced by the helper function percent().
s["Has children"] = percent(d["has_children"] == "Yes")20% of Master’s students and 40% of PhD students have children, 26% overall. Because describe() builds a column for any group of students, one new line in one function adds the row to every column of the table: the helper-function habit at work.
Exercise 3: A sentence for the effect of support on GPA
Write a reporting sentence, with the numbers inserted by code, for the effect of support on GPA in the chapter’s regression model.
The chapter’s helper that formats p-values (reporting “p < .001” for very small values) is format_p(p_val).
format_p(p_val)The sentence reads: “Each one-point increase in supervisor support was associated with a GPA 0.11 points higher (95% CI 0.08 to 0.14, p < .001), holding sleep, study hours, and stress constant.” Every number comes from the model, rounded as a journal would print it.
Exercise 4: A third panel for the thesis figure
Add a third panel to the thesis figure: wellbeing by faculty as a box plot.
This exercise needs matplotlib subplots and the project’s figure code, so it is done in the download project.
In scripts/02_analysis.py, create three subplots:
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(13, 4))
# ... panel 1 and 2 ...
sns.boxplot(data=study, x="faculty", y="wellbeing", ax=ax3, color=soft)
ax3.set_title("C", loc="left", fontweight="bold", fontsize=12)
ax3.tick_params(axis="x", rotation=30)Exercise 5: A method for your own question
Choose a research question from your own field. Using the chapter’s guide to choosing a method, decide which method you would use, and which chapter of this book you would reread first. Write your answer first, then open the model answer.
An example from public health: “Does a text-message reminder programme reduce missed clinic appointments, among patients followed for a year?” The goal is to explain or compare: does the programme make a difference? The outcome, missing an appointment, is yes or no, pointing to logistic regression (Chapters 7 and 8). But each patient has multiple appointments over the year, so observations are repeated, requiring a logistic mixed-effects model with a random intercept for each patient (Chapter 10). If clinics were randomised to the programme, clinic would be an additional hierarchical level. The chapter to reread first is Chapter 10, then Chapter 5 on experimental design to evaluate causal inference.
Exercise 6: The chain of reasoning for RQ2
Complete the chain of reasoning for RQ2, whether students sleep less than 7 hours, using the results of Chapter 7. Run the test, then fill in the chain.
The hypothesis tests whether average sleep is less than the benchmark of 7 hours.
sleep_test = stats.ttest_1samp(sleep_clean, popmean=7, alternative="less")Average first-semester sleep is 6.48 hours (95% CI 6.40 to 6.57, n = 594), and the one-sided test gives \(p < .001\). The conclusion is descriptive, not causal, which matches the research question: it reports how much students sleep, not what causes sleep deficits.
Go further
These exercises go beyond the book.
Exercise 7: A helper for confidence intervals
Write a helper function that formats an estimate with its 95% confidence interval, and use it in three sentences.
The upper confidence bound in the string formatting is high.
return f"{estimate:.{digits}f} (95% CI {low:.{digits}f} to {high:.{digits}f})"One helper formats every interval consistently with custom decimal precision.
Exercise 8: The chain of reasoning for RQ4
Complete the chain of reasoning for RQ4, whether stress differs between faculties, with a one-way ANOVA, \(\eta^2\), and Tukey’s test.
Inspect the Tukey table’s reject column to see which specific pairwise differences are statistically significant (\(p < 0.05\)).
# Tukey HSD results show Health Sciences (3.37) vs. Humanities (3.03) is the only significant pair (reject = True).\(F(4, 595) = 4.15\), \(p = .003\), \(\eta^2 = 0.03\). The difference is statistically significant, but small: faculty membership explains only 3% of the variance in student stress.
Exercise 9: Table 1 by faculty
Use the same describe() function to build the sample table with one column for each faculty.
Inside the loop, filter study where study['faculty'] == f.
table_1[f] = describe(study[study["faculty"] == f]).valuesOne function and a loop produce five faculty columns, letting readers compare subgroup demographics before evaluating models.
Exercise 10: Choosing methods
Use the chapter’s guide to choosing a method to decide which method suits each of these five research questions.
- How many hours a week do nurses in a hospital work, on average?
- Is the number of hours worked related to nurses’ burnout scores, allowing for age and ward?
- Burnout was measured every three months for two years: does it rise over time?
- Can the nurses who will leave the hospital within a year be identified from their records?
- Are there groups of nurses with similar patterns of shifts, overtime, and sick days?
- Describe: mean with parametric or bootstrap confidence interval, histogram (Chapters 4, 6, 7).
- Explain: multiple regression (Chapter 8); if ward clustering is strong, a mixed-effects model with random ward intercepts (Chapter 10).
- Longitudinal change: mixed-effects growth model with random slopes for nurses over time (Chapter 10).
- Predict: binary classification (logistic regression, gradient boosting) evaluated via cross-validated AUC and precision-recall (Chapters 11, 12, 13).
- Find groups: unsupervised clustering (K-Means, GMM) on standardized shift features, reported as descriptive profiles (Chapters 9, 14).
Check your understanding
Answer each question in your own words first, then click to see a model answer.
1. Why should every number in a thesis be traced to code?
So that every result can be checked, repeated, and updated. A number calculated by code cannot be mistyped, stays correct when raw data is re-exported, and documents its provenance. An examiner asking “how was this calculated?” can be directed to the exact script line.
2. What is the difference between a result and a conclusion?
A result is the statistical output (e.g. \(p = .003\), \(\beta = 0.11\), \(\text{OR} = 3.6\)). A conclusion interprets what that number means in relation to the substantive research question, conditioned on the research design, construct operationalization, and threats to internal/external validity.
3. Why is the workshop conclusion the only causal one in the chapter?
Because workshop invitation was randomly assigned by the researcher, ensuring baseline equivalence between groups. Sleep, stress, and support were observed without experimental manipulation, leaving open the possibility of confounding.
4. What is a limitations section for?
To define the boundaries of inference: unmeasured confounders, measurement errors (e.g., self-reported sleep), and population constraints (single university cohort). It demonstrates critical methodological maturity.
5. What are reporting standards such as JARS, CONSORT, and STROBE for?
They provide explicit reporting checklists specifying all participant, measurement, and statistical details necessary for peer review, scientific evaluation, and meta-analytic synthesis.
Do it yourself
These tasks have no starter code and no answers. The code space is empty and ready to run; data and helpers are preloaded.
1. The capstone: choose an unexamined research question from the dataset (such as whether exercise is associated with wellbeing, allowing for sleep and study mode), and complete the entire chain of reasoning.
2. Check your capstone report against the JARS criteria for participant description, measurement reliability, and complete statistical reporting (estimates, standard errors, confidence intervals).
3. Exchange your report with a peer and evaluate their chain of reasoning: do their conclusions remain strictly within what their research design supports?
Work on your own computer
The complete thesis project, with the folders data-raw, scripts, data, and output: scripts/01_clean_data.py turns the raw survey export into clean data, scripts/02_analysis.py runs the analyses and makes the figure, and results.qmd is the results chapter, with every number written as inline code. exercises.txt lists the project tasks, and exercises.py and solutions.py hold the Python parts of this page.