Cluster raw user research observations into findings a team can defend: code interview and usability notes against a written codebook, group codes bottom-up into themes, turn topic labels into finding statements, flag themes that rest on one participant, run a coder agreement pilot where the approach calls for one, and keep the quote, participant and session behind every claim. Use when synthesizing interviews, usability sessions, field notes or open-ended survey answers, when a readout needs an audit trail, or when themes feel tidy but thin. Triggers on "affinity mapping", "affinity diagram", "synthesize these interviews", "cluster these notes", "thematic analysis", "codebook", "themes from this research".
./install.sh affinity-mappingname: affinity_mapping description: >- Cluster raw user research observations into findings a team can defend: code interview and usability notes against a written codebook, group codes bottom-up into themes, turn topic labels into finding statements, flag themes that rest on one participant, run a coder agreement pilot where the approach calls for one, and keep the quote, participant and session behind every claim. Use when synthesizing interviews, usability sessions, field notes or open-ended survey answers, when a readout needs an audit trail, or when themes feel tidy but thin. Triggers on "affinity mapping", "affinity diagram", "synthesize these interviews", "cluster these notes", "thematic analysis", "codebook", "themes from this research".
Turn a pile of interview notes, usability observations and open-ended answers into findings that hold up when someone asks "says who, in which session, in what words". Affinity diagramming, devised by Jiro Kawakita in the 1960s as the KJ method, groups individual observations by their natural relationships instead of sorting them into categories chosen in advance. This skill adds the parts a quick workshop version usually skips: a written codebook before clustering, a check on how much weight each theme can carry, and a readout where every claim traces back to a quote.
Use it for applied product and UX research synthesis. For a formal academic thematic analysis, follow the approach rules in step 1 and cite the method you actually used.
Choose one, and record the choice at the top of the codebook:
Mixing these up is the common failure. Do not report a kappa score for a reflexive study, and do not skip the reliability pilot for a coding-reliability study and call the result rigorous. Braun and Clarke's six phases still describe the shape of the work in any approach: get familiar with the data, generate codes, build candidate themes, review themes, define and name themes, write the report. The phases loop back on each other. They are not a one-way checklist.
Break transcripts and session notes into single-idea observations. One note carries one observation, one participant id, one session id, and a verbatim quote or a close observation note. A note that bundles three ideas will fit three clusters badly.
Keep paraphrase out of the quote field. If you shorten a quote, mark the cut. A reader who cannot see the original wording cannot judge the claim built on it.
Lay the observations out in a table with columns observation_id, participant_id, session_id, quote, code and theme. The example in assets/example-observations.csv shows the shape, and scripts/theme_check.py reads exactly that shape.
Start from references/codebook-template.md. Every code gets a definition, an inclusion rule, an exclusion rule that names the near miss and where it belongs instead, and one real positive and negative example with participant and session ids.
Code the whole set against the current codebook version. When a segment fits two codes, apply both and note the overlap instead of forcing a single choice. When a segment fits no code, park it in an unclassified row and review the parked set before clustering. New codes usually hide there.
Change the codebook only at a version boundary. Record the change, then recode the earlier segments the change affects, or write down why they stand.
For codebook and coding-reliability work, have a second coder code a pilot subset independently, before seeing your codes. Pick the subset on purpose, covering early and late sessions and at least one difficult transcript, and record how you picked it.
Score it with:
python3 scripts/theme_check.py --agreement agreement.csv
The CSV needs unit_id, coder_a and coder_b. The script reports percent agreement (Po), chance agreement (Pe) and Cohen kappa, computed as (Po - Pe) / (1 - Pe), plus every disagreement by unit. Kappa sits at or below percent agreement for the same data, because it removes the agreement chance alone would produce. Read kappa with the commonly used Landis and Koch style bands: 0.00 to 0.20 slight, 0.21 to 0.40 fair, 0.41 to 0.60 moderate, 0.61 to 0.80 substantial, 0.81 to 1.00 almost perfect. Those bands are a convention, not a law. Other published sets, such as McHugh's, are stricter. Always report Po next to kappa, because when one code dominates the data kappa can read low even when coders agree often.
Treat disagreements as codebook defects first and coder errors second. Each disagreement should end in a split code, a merged code, a sharper exclusion rule, or a recorded boundary call. Never settle a disagreement by vote and leave the codebook unchanged. Cohen kappa covers two coders. For three or more, use a multi-rater measure such as Fleiss kappa or Krippendorff alpha, and say which one you used.
For reflexive work, skip the pilot. Instead, have a second reader argue for a different reading of three themes, and file the argument and your response with the worksheet.
Group observations and codes by what they share, following the NN/g order: generate the notes, organize them into clusters, then prioritize clusters and next steps. Practical rules from that method and from the KJ tradition:
Fill in references/clustering-worksheet.md for each cluster, then run:
python3 scripts/theme_check.py observations.csv
The script flags themes resting on a single participant, themes with a single observation, duplicate observation ids, and observations missing a quote, session, code or theme. Then do the checks a script cannot do: internal fit, separation from neighbouring themes, a search for counter-evidence, and the worst-fit test from the worksheet.
Handle a single-participant theme honestly. A theme does not need to appear in every interview to matter, and a rare theme can be the most important one in the set. But one participant cannot support a claim about participants in general. Demote it to a lead, attach the follow-up question that would test it, and label it as a lead in the readout.
A cluster label names a topic, such as "reports" or "onboarding". A finding says what was learned, for whom, and under what condition, such as "when the standard report cannot produce the cut a manager asks for, participants move the work into a spreadsheet rather than wait". If your sentence would still be true before the research ran, it is a topic, not a finding. Rewrite it.
Attach to each finding its observation ids, participant count, session count, strongest verbatim quote, known counter-evidence or limit, and a confidence call: pattern, lead, or contradiction. references/worked-synthesis.md walks a seven-observation set through every step, including a flagged theme that gets demoted in the readout.
Close by ranking findings by the decision they inform, not by cluster size alone. A large cluster can be low stakes, and a small one can block a launch. Save the coded observations table, the codebook version used, the filled worksheet and the board state with the readout. Synthesis that cannot be re-walked by someone else is an opinion with good formatting.
scripts/theme_check.py reads.references/codebook-template.md.references/clustering-worksheet.md, including the script output.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.