Template - Methods and Results Notebook
How to use this
You are going to build five small files. Each one is tiny and does exactly one job. Copy them in the order below, swap in your own variables and analyses, and then render report.qmd. Out comes a Word document in which every number is produced by your code — so when your data changes, you re-render and everything updates itself. Nothing is ever typed by hand.
This is the workflow from the post "Make Your Analysis Reproducible: A Document That Updates Itself" — prefilled, so you don't start from a blank file.
One rule to hold onto as you read: your.qmdis a document, not a script. The prose reads like a real Methods and Results section; the code chunks justsource()the scripts that do the work. Keep the analysis in the scripts and the writing in the document.
The map
my-report/
├─ report.qmd ← THE file you render (your writing + hidden code)
├─ setup.R ← loads your packages
├─ R/│ ├─ prepare_data.R ← load → clean → (impute) → one tidy dataset
│ ├─ analysis.R ← run your tests, SAVE each result
│ └─ apa.R ← helpers that format results the APA way
└─ data/
└─ data.csv ← your data① setup.R
You add packages to this file when you need them
# The only place you load packages.
library(dplyr) # cleaning
library(mice) # imputation (optional)
library(broom) # tidy model results
library(flextable) # tables that render straight to Word② R/prepare_data.R
This is where you do anything related to cleaning data.
# 1. Load
raw <- read.csv("data/data.csv")
# 2. Clean — keep only what you need
df <- raw |> select(outcome, predictor, group) |> mutate(across(everything(), as.numeric))
# 3. Impute missing values (optional — delete these lines if you don't need it)
df <- mice(df, m = 5, printFlag = FALSE) |> complete(1)
# => df is now clean and ready.Build the files (2 of 2)
③ R/analysis.R — run the tests, save the results
model <- lm(outcome ~ predictor, data = df) # Notes on choice can be placed here
t_test <- t.test(outcome ~ group, data = df) # References can also be placed here④ R/apa.R — format results the APA way
Reusable helpers, so every result looks consistent everywhere it appears.
# Inline sentence, e.g. "R² = .42, F(2, 97) = 12.30, p = .001"
apa_fit <- function(m) {
g <- broom::glance(m)
sprintf("R² = %.2f, F(%.0f, %.0f) = %.2f, p = %.3f",
g$r.squared, g$df, g$df.residual, g$statistic, g$p.value)
}
# A clean Word table from any model
apa_table <- function(m) {
flextable(broom::tidy(m)) |> autofit()
}The main file
⑤ report.qmd — the document that ties it all together
---
title: "Methods & Results"
format: docx
execute:
echo: false # hide all code
warning: false # hide all warnings
message: false # hide all messages
---
```{r}
#| include: false
source("setup.R")
source("R/prepare_data.R") # -> df
source("R/apa.R") # -> apa_fit(), apa_table()
```
# Methods
A linear regression predicted the outcome from the predictor.
```{r}
#| include: false
source("R/analysis.R") # -> model (saved, not printed)
```
# Results
The model explained the outcome, `r apa_fit(model)`.
```{r}
apa_table(model) # the only line that prints
```That's the whole thing. Render report.qmd and you get a Word document with your Methods and Results, the statistics woven into the prose by apa_fit(), and a formatted table from apa_table(). Change the data in data/data.csv, render again, and every number updates on its own.