Project setup and reproducibility

The shared mechanics behind both group projects

What this page is for

Both group projects use the same repository structure, the same .gitignore, the same documentation files, and the same reproducibility test. Rather than say all of that twice, it lives here.

You do not need to read this end to end before starting. Work through Setting up the repository in your project’s first week, then come back to the other sections as you reach them. The project brief tells you when.

The starter zip does most of this for you. Download the one for your project — Project 1 or Project 2 — and you begin with the structure, the .gitignore, and the documentation templates already in place. What follows is what those files are for, so you can use them well rather than just having them.

Repository structure

Your team’s repository has this structure — and you do not have to build it by hand. project-1-starter.zip contains all of it, ready to unzip:

project-1-team-name/
│
├── README.md
├── .gitignore
├── project-1-team-name.Rproj       # you create this in RStudio; named after your folder
│
├── data/
│   ├── README.md
│   ├── raw/                         # local only / ignored by Git
│   └── derived/                     # local only / ignored by Git
│
├── documentation/
│   ├── project-plan.md
│   ├── data-provenance.md
│   └── codebook.csv
│
├── programs/
│   ├── p1_data_brief.qmd
│   └── p1_data_brief.html          # renders here, next to its source
│
└── output/
    └── figures/            # exported .png files, if you save any

The exact repository name is up to your team. The structure is not — keeping everyone on the same structure is what makes the project easier to read, troubleshoot, and grade.

The rendered report lives beside its .qmd, exactly as in every lab

Quarto writes report.html next to report.qmd. That is what has happened in every lab since M02, and nothing changes here — do not move the HTML into output/, and do not add output-dir: to the YAML to redirect it. Keeping the source and its render in one folder is what makes “re-render and see” a single click.

output/figures/ is for something different: figures you deliberately export as standalone .png files. You met the tool in M03 — the Data Visualization module shows ggsave() with here() and explains why you set the width and height at save time. Here it is with this project’s path:

ggsave(here("output", "figures", "fig1-prevalence-by-group.png"),
       my_plot, width = 6.5, height = 3.6, dpi = 300)

M03’s example writes straight into output/; here you add a figures/ subfolder, because a project accumulates more exported files than a single lab does and they are easier to find grouped together.

Note here() doing the work: the path resolves from the project root, so it is the same string on every teammate’s laptop.

Whether you need this at all depends on your presentation. If you present by scrolling the rendered report, every figure is already in it and output/figures/ may hold nothing but its .gitkeep — that is a perfectly good outcome. If you build slides, exporting the figures you want to show is easier than screenshotting them.

Two things follow, and both matter now that we grade the repository:

  • The rendered .html must be committed. Your .gitignore excludes data/raw/, data/derived/, and *_files/, but not programs/*.html. Check that the rendered file appears in GitHub Desktop’s Changes list before your final commit.
  • The report is self-contained. The template sets embed-resources: true, so the HTML bundles its own images and styles into one file. That is why excluding *_files/ is safe, and why a grader can open your report straight from GitHub without anything else.

Setting it up · step by step

We give you the skeleton. Download project-1-starter.zip — it contains the folder structure above, the .gitignore, the documentation templates, and the report skeleton, all ready to go.

That is deliberate. Clicking New Folder five times teaches you nothing, and the .gitignore in particular is a file you need to understand, not to retype. What the starter does not do is make it a repository or publish it — those are the Git skills, and they are yours.

1 · One person sets up the folder. Pick a repo owner (an administrative role only — no extra authority over the analysis). Everything in this step happens on that person’s laptop.

a. Unzip the starter somewhere you will find it again — alongside your PSY652_project folder is a good choice, not inside it.

b. Rename the unzipped folder for your team, with no spaces: project-1-team-name.

c. Open it in RStudio. File → New Project → Existing Directory, point at the folder, and click Create Project. RStudio reopens with that folder as the working directory and creates an .Rproj file named after it — so project-1-team-name.Rproj. That file is what makes here() resolve from anywhere inside the project.

d. Turn on hidden files, and check what you got. Two of the most important files in the project start with a dot, which means your file browser hides them by default. In RStudio’s Files pane click More (the gear icon) → Show Hidden Files. Leave it on for the rest of the project.

You should now see .gitignore at the top level and a .gitkeep inside data/raw/, data/derived/, and output/figures/. Compare the whole thing against the tree above before moving on.

What those two dotfiles are doing

.gitignore lists what Git should leave alone — above all, your data. Read the next section before your first commit; it is short, and it is the difference between a clean repository and one with a survey file permanently baked into its history.

.gitkeep is a placeholder, and it exists because of a quirk worth knowing: Git tracks files, not folders. An empty folder cannot be committed at all, so without these your teammates would clone the project and find data/raw/ simply missing — then follow data/README.md, be told to put the raw file there, and have nowhere to put it. The .gitkeep files are empty on purpose. Leave them.

2 · Make it a repository and publish it. Open GitHub Desktop → File → Add Local Repository, choose your folder, and follow the same create a repository prompt you met in the M02 lab. Then click Publish repository and choose Private.

3 · Add the graders, and invite your teammates. On github.com add KimberlyHenry and alliekom as collaborators, then your teammates. Each teammate clones through GitHub Desktop. Full steps, with the menu paths, are in Collaborating with Git — read that page before your first shared work session, not after your first conflict.

Check this before you commit anything

Open GitHub Desktop and look at the Changes list. If you can see a data file under data/raw/ or data/derived/ — a .sav, a .csv, an .rds — your .gitignore is not doing its job, so stop and fix it before committing. Once a data file is in the history, removing it is genuinely difficult, and for restricted data it may be impossible to undo.

What you should see listed: README.md, .gitignore, the .Rproj you just created, data/README.md, the three .gitkeep placeholders, the documentation/ templates, and programs/p1_data_brief.qmd.

The .gitkeep files belong there — they are how the empty folders survive a clone. Seeing data/raw/.gitkeep is the ignore rule working correctly; seeing data/raw/atp-w####.sav is not.

Your .gitignore

Create this file at the top level of the repository, before your first commit. Copy it exactly.

.gitignore
# ---- Data: never commit ----------------------------------------------------
# Raw files are often large, sometimes restricted, and always re-obtainable
# from documentation/data-provenance.md -- whether you downloaded them from Pew
# or from a paper's data repository. Derived files are rebuilt by your code.
# The trailing /* ignores each folder's CONTENTS rather than the folder itself.
data/raw/*
data/derived/*

# ...but DO track the placeholders, so a fresh clone still has somewhere to put
# the source file and somewhere for your code to write the derived one.
# The leading ! un-ignores a path that an earlier rule excluded.
!data/raw/.gitkeep
!data/derived/.gitkeep

# ---- R and RStudio ---------------------------------------------------------
.Rproj.user/
.Rhistory
.RData
.Ruserdata

# ---- Quarto ----------------------------------------------------------------
/.quarto/
*_files/
*_cache/

# ---- Operating system junk -------------------------------------------------
.DS_Store
Thumbs.db

The two ! lines are the ones people get wrong — and the reason is a rule about Git that is worth knowing now rather than discovering during your clean-clone test. Git tracks files, not folders. An empty folder cannot be committed at all, which is why the starter ships a .gitkeep inside each folder that would otherwise be empty.

That creates a trap. If the ignore rule were written data/raw/ — the whole folder — it would swallow the .gitkeep inside it too, and the folder would vanish on a fresh clone. Your teammate would follow data/README.md, be told to put the raw file in data/raw/, and find no such folder. Writing data/raw/* instead ignores the folder’s contents while leaving the placeholder un-ignorable by the following ! line.

Note that data/README.md needs no ! rule of its own: nothing here ignores data/ itself, only what sits inside raw/ and derived/, so that file is tracked already.

Why this differs from your course project’s .gitignore. That one ignores a single flat data/ folder, because everything in it arrived ready to use. Yours has to distinguish the raw file you downloaded from the analytic file your code builds — and keep a tracked note explaining both.

And a reversal worth catching before it bites you. Your course project’s .gitignore ends with these two lines:

PSY652_project/.gitignore
output/
*.html

That is deliberate there: lab HTML regenerates from the .qmd, so the repo keeps the source and you submit the rendered file to Canvas. Do not carry those two lines into your project repository. Here the rendered report is the deliverable — we grade it from the repo — so programs/p1_data_brief.html and anything in output/figures/ must be tracked. The .gitignore above is already correct; the mistake to avoid is adding to it out of habit.


The documentation files

README.md · the front door

Your starter ships a README skeleton already tailored to your project — Project 2’s names its own report file and asks for the published result it reproduced, where Project 1’s asks for the research question. The shape below is Project 1’s; fill in whichever one you were given.

Your repository README must contain:

# Project title

Team members

## Research question

## Project summary

One short paragraph describing the question and main finding.

## Repository structure

- `programs/` — your Quarto analysis **and the HTML it renders to**
- `documentation/` — project plan, provenance, and analytic codebook
- `data/` — local raw and derived data; not tracked by Git
- `output/figures/` — any figures you export with [ggsave()]{.fxn-name}, for reuse outside the report

## Reproduce this project

1. Clone the repository.
2. Obtain the data using `documentation/data-provenance.md`.
3. Place the raw file at the documented path.
4. Open the `.Rproj` file.
5. Render `programs/p1_data_brief.qmd`.

## Required R packages

[List the packages actually used.]

## Data availability

Explain why the raw data are or are not included in Git.

## Reproducibility check

Clean-clone test completed by [name] on [YYYY-MM-DD].
Cloned fresh, obtained the raw data as documented above, and rendered
`programs/p1_data_brief.qmd` from a restarted R session without errors.

documentation/data-provenance.md · where the data came from

This file answers one question: could someone else obtain exactly the file you analyzed? Fill in every line; write “not applicable” rather than leaving a blank.

documentation/data-provenance.md
# Data provenance

## Source
Pew Research Center, American Trends Panel

## Wave
Wave [number] — [official wave name, if it has one]

## Field dates
[Start date] to [end date]

## Report or page that led us here
[Title]
[URL]

## Download URL
[The exact page you downloaded from, not just pewresearch.org]

## Date accessed
[YYYY-MM-DD]

## Downloaded filename
[The filename exactly as it arrived, before any renaming]

## Registration or data-use requirements
[What you had to agree to. Pew requires an account and acceptance of terms.]

## Expected local path
data/raw/[filename]

## Redistribution
[May this file be shared publicly? Course policy for Pew ATP: do not
commit or redistribute the microdata. Each teammate obtains the wave
from Pew under their own account and places it in data/raw/.]

## Notes
[Anything a future reader would need: a wave that was re-released,
a codebook that lives in a separate download, an oddity you noticed.]

Write this the day you download the file, not at the end. Access dates and exact filenames are the first things people forget, and they are the two that make a file findable again.

documentation/project-plan.md · what you set out to do

Your Week 1 proposal, kept in the repository and updated as the project develops. It exists so that a reader — and your future selves — can see what you intended before you saw any results.

documentation/project-plan.md
# Project plan

## Team
[Names, and who is taking first responsibility for which section]

## Topic
[The substantive issue]

## Research question
[One focused descriptive question]

## Intended reader
[Who would benefit from knowing the answer, and why]

## ATP wave
[Wave number and why it can answer the question]

## Focal variables
[Raw Pew variable names, with a short description of each]

## Planned comparison
[The subgroup, cross-tab, or second dimension you expect to use]

## Survey weight
[The wave-specific weight variable name, even if you analyze unweighted]

## Measurement question we already have
[One honest uncertainty about how the construct was measured]

## Feasibility
[One sentence: why this fits in four weeks with M01–M05 tools]

## Changes to this plan
[Append-only. Date each change and say why it happened.
"2026-10-02 — dropped the income comparison; too much missingness."]

That last section matters more than it looks. Plans change for good reasons, and a documented change is a sign of a thoughtful team. An undocumented change makes it much harder for a reader to tell what happened and why.

data/README.md · what belongs in the data folders

Small, tracked, and the only thing inside data/ that GitHub will show. Without it, someone cloning your repository finds two empty folders and no instructions.

data/README.md
# Data

The data files themselves are **not** tracked by Git. This file is.

## data/raw/
The file exactly as downloaded, never edited by hand.

Expected file: `[filename]`

To obtain it, follow `documentation/data-provenance.md`.

## data/derived/
The analytic dataset, built from the raw file by
`programs/p1_data_brief.qmd`. Do not edit by hand — if something is
wrong, fix the code and re-render.

Expected file: `analytic.rds`

## If you just cloned this repository
Both folders will be empty. Obtain the raw file, place it in
`data/raw/`, then render `programs/p1_data_brief.qmd` — it rebuilds
`data/derived/` for you.

documentation/codebook.csv · what the analytic variables mean

Use the project codebook format — seven columns:

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

Document only variables that actually enter the analysis.

Note the two extra columns. The codebooks shipped with the course datasets carry five columns, because those files arrived already prepared — someone else did the downloading and recoding. Yours does that work, so source and derivation are what let a reader trace each analytic variable back to the raw Pew variable it came from. The Analytic Codebook Guide explains the difference and shows worked examples of both.

See the Analytic Codebook Guide.


GitHub collaboration expectations

The repository is a record of your team’s work, and it should tell a readable story of how the project developed.

Each team member should:

  • clone the shared repository,
  • pull before beginning a work session,
  • make substantive contributions,
  • use meaningful commit messages,
  • push completed increments,
  • and communicate before editing the same section of a file.

Good commit messages describe a completed change:

Add Pew import and variable recodes
Build age-group comparison figure
Revise measurement limitation
Add Table 1 and missing-data note

Avoid:

stuff
update
final
final2

You are not graded on the number of commits. The history should simply show ongoing, shared development rather than a one-time upload at the deadline.

Never commit:

  • downloaded data that your .gitignore excludes,
  • passwords,
  • API keys,
  • access tokens,
  • or files containing private credentials.

The clean-clone test

Before submission, choose a teammate who was not the primary data-prep person.

This is the best way to check whether the project really stands on its own rather than depending on one person’s laptop or memory.

That person should:

  1. clone the repository into a new folder,
  2. read the README,
  3. obtain or copy the raw data into the documented location,
  4. open the .Rproj,
  5. restart R,
  6. render p1_data_brief.qmd from beginning to end.

No objects should need to be created manually in the Console. No absolute paths should need editing.

This is the project’s reproducibility test.