Group Project

Work with your group across three afternoon sessions to take a real dataset from raw CSVs to a short presentation.

Datasets

Your group will work with one of two datasets, both included in the participant codespace under data/:

  • Group A — Yogurt study (data/group_a_yogurt/): participant metadata, qPCR results, and Luminex cytokine measurements from a randomized study of yogurt consumption.
  • Group B — Menstruation study (data/group_b_menstruation/): longitudinal sampling across the menstrual cycle, with participant metadata, Luminex cytokines, and flow cytometry.

Pick a biological question that interests your group and build toward a short presentation by Friday.

Session 1 — Wednesday: Build a data dossier

Your group is going to build a data dossier: a Quarto report that explains your dataset table-by-table, shows what the numbers look like, and ends with a shortlist of biological questions you plan to explore more on Thursday.

Use Pi to move fast, then slow down and interrogate/iterate on what Pi produced. Pi will hand you a working draft in seconds. The learning happens when you read its code, ask it for clarification, run it, and check that it’s actually true.

Work in parallel, then compare

Everyone should try prompting Pi on their codespace. Compare often. When someone in your group got more out of the dataset than you did, ask:

“What did you ask Pi for?”

The Pi loop

Start by copying this prompt into the terminal:

I'm exploring a new dataset in `data/`. Ask me which group I'm in, then read all
the CSV files and give me, for each one, what a single row represents and
what every column means. Always make files in the "group_project" folder.

I want the output in the form of a qmd document using R and tidyverse code for each code chunk. I want 
format:
  html:
    toc: true
    code-fold: true
    embed-resources: true 
Launch the preview as a detached background process so it survives your shell
exiting and keeps watching for changes:
    PORT=4321
    setsid quarto preview <qmd_file_name> --no-browser --port $PORT \
      > /tmp/quarto-preview.log 2>&1 < /dev/null &
We're in a GitHub Codespace, so localhost won't work from my browser. Build the
forwarded URL from the Codespace env vars and print it as a clickable terminal
hyperlink (short visible text, so it won't wrap and break the link):
    URL="https://${CODESPACE_NAME}-${PORT}.${GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}/"
    printf '\n\e]8;;%s\a▶ Open Quarto preview\e]8;;\a\n' "$URL"
    echo "log: /tmp/quarto-preview.log"

This might take 2-5+ minutes for the model to accomplish. Then start these steps below:

  1. Ask. Give Pi a concrete task. (for instance “Tell me what the second code chunk does, line by line”)
  2. Read. Actually read the code and the response it wrote. What does each line do? If a line is mysterious, ask Pi to explain that line.
  3. Verify. Don’t just trust it; it’s still your job to produce trustworthy analysis. Check it two ways: by doing (run a little of your own code to count the rows, count() a column’s values, or confirm a join lines up) and by asking (have Pi tell you how it would verify the claim, then run what it suggests).
  4. Iterate. Refine, then write one sentence in your report saying what you now know.

Pi might be completely right, and that’s fine. You verify anyway, because the goal is for you to understand the dataset.

Your report

One rendered HTML report per group. Start your .qmd with a header that turns on a table of contents, folds code by default, and bundles everything into a single self-contained file:

---
title: "Group A — Data Dossier"
format:
  html:
    toc: true
    code-fold: true
    embed-resources: true
---

code-fold keeps the report readable as prose while leaving every chunk one click away; embed-resources makes the HTML a single file you can hand to anyone.

The afternoon (1:30–5:00)

  • 1:30–1:45 · Kick off & set up. Each person creates their report .qmd with the header above, loads tidyverse and here, and confirms the data path works. Goal: a Quarto doc that renders before you explore anything.
  • 1:45–2:45 · Map the dataset, fast. Lean on Pi for speed. For every table, answer: what is one row, and what does each column mean? Get a rough draft of the whole map written as prose in your report.
  • 2:45–3:00 · First verification. Slow down. Each person picks two claims from their map and confirms them — by running your own code and by asking Pi how it would check. Not hunting for mistakes; building confidence that you really know what’s in the tables.
  • 3:00–3:30 · Break.
  • 3:30–4:30 · Explore & plot. Go deep on the numbers: distributions, skew, suspicious values, missing data. Make your first plots inside the report and iterate on them — remaking one plot three times teaches more than making three different plots once.
  • 4:30–5:00 · Distill & render. Pool everyone’s findings into the group report. Turn what you found into a shortlist of biological questions for Thursday. Render to HTML.

Walk away with

  • A rendered data dossier that explains every table and shows a few plots
  • A shortlist of 2–4 candidate questions for Thursday
  • A sense of which of you asks Pi the sharpest questions, and why

Session 2 — Thursday: Table 1, comparisons, and models

Wednesday’s dossier told you what is in the dataset. Thursday you take one of your candidate questions and answer it three ways: describe the participants, compare the groups, and fit a model. The output this time is the analysis a paper would actually show.

You keep working with Pi in the same loop as Wednesday — ask, read, verify, iterate — adding to the report you already have.

The three pieces

Build these for the question your group picked. You don’t have to use all three; pick the ones your question needs, and be ready Friday to say why.

  1. A Table 1 with gtsummary. tbl_summary(by = <group>) describes your participants and add_p() tests each row. Go variable by variable and decide whether the default summary (median (IQR), counts (%)) and the default test are the ones you want, then override the ones that aren’t.
  2. A comparison figure with ggpubr. ggboxplot(...) + stat_compare_means() shows one outcome across your groups with the p-value drawn on the plot. Reach for facet_wrap() when you want to screen several outcomes at once.
  3. A model with tbl_regression(). Fit lm(), glm(), or lmer() for the effect you care about — adjusting for a covariate, or accounting for repeated samples on the same participant — then turn the fit into a coefficient table. Fit the model once and report it; never refit just to make a table.

Add to the report you already have

Your dossier .qmd from Wednesday is the right place for all of this. Your preview may still be running; if not, relaunch it the same way you did in Session 1. When Pi edits the file and saves, the preview reloads on its own, so keep it visible next to the terminal and watch each change land.

Ask Pi to add to the file, and point it at the section you mean:

In group_project/<your_report>.qmd, add a new section called "Table 1".
Use gtsummary to build a tbl_summary of the participant metadata split by
<group>, then pipe to add_p() to test each row. Append it to the file —
don't rewrite what's already there. I'll watch the preview reload.

Then iterate one change at a time, reading the preview after each:

Age should be mean (SD) with a t-test, not median (IQR). Override just that
one row and leave the rest of the table alone.
Now add a ggpubr boxplot of <outcome> by <group> with a Wilcoxon p-value on
it, right below the table.

The first version is rarely the one you want: the wrong test, the wrong grouping, ugly labels. That is normal. Fix one thing, watch the preview, read what changed, and decide whether it is better. That loop is the work.

Verify, same as Wednesday

A model fit and a p-value look authoritative whether or not they are right. Before a result goes in your Friday talk, check it. Does the test match the data (skewed data wants Wilcoxon, symmetric wants a t-test)? Does the figure’s p-value agree with the table’s? Ask Pi how it would confirm the result, then run that check yourself.

The afternoon (1:30–5:00)

  • 1:30–1:45 · Pick the question. As a group, settle on one question from Wednesday’s shortlist and the groups you will compare. Write it at the top of the section you’re about to build.
  • 1:45–2:45 · Table 1. Build tbl_summary() |> add_p(), then go column by column deciding which defaults to keep and which to override. Land on one Table 1 the group agrees on.
  • 2:45–3:00 · Sanity check. Confirm the test choices match the distributions you saw on Wednesday.
  • 3:00–3:30 · Break.
  • 3:30–4:30 · Compare and model. Add the ggpubr figure(s) for your headline comparison, then fit the model that answers your question and report it with tbl_regression(). Iterate on the plot — remaking one figure three times beats making three different ones once.
  • 4:30–5:00 · Distill & render. Decide which table and which figure tell your story, write the sentence or two that goes with each, and render to HTML.

Walk away with

  • A Table 1 you would feel OK putting in a paper
  • One or two ggpubr figures of the comparisons you care about
  • At least one model reported with tbl_regression()
  • A clear sense of what your group will say on Friday

Full prompts live in group_project/README_session2.md in your codespace.

Session 3 — Friday: Present your findings

Each group gives a short presentation (about five minutes) to the rest of the workshop. The goal isn’t to impress — it’s to share what you found, what surprised you, and what you’d want to do next.

Bring:

  • Your question
  • One or two takeaways from your Table 1
  • The figure that best tells your story
  • A short list of limitations and next steps

Full prompts live in group_project/README_session3.md in your codespace.

Example presentations

Want to see where this can go? These two example decks were built from the exact datasets in your codespace, using only the tools from Modules 3–6 (tidyverse, gtsummary, ggpubr, and lme4), assembled with an LLM assistant. Each one walks a Table 1 and a few exploratory plots, then tells three short data stories — question, code, figure, interpretation.

They are a target to aim for, not a template to copy. Your question and your dataset are your own.