play icon for videos
← Academy
SOPACT ACADEMY · SURVEY INTELLIGENCE · ANALYZE

Compare Two Cohorts Without Fooling Yourself

Benchmark two cohorts on the same metrics, normalise for size and program length, separate the real delta from confounds, and grade the comparison green, amber, or red — so a raw gap never gets reported as an improvement.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> @keyframes pulseDot{0%,100%{opacity:1}50%{opacity:.35}} *{box-sizing:border-box} body{margin:0;font-family:'Hanken Grotesk',-apple-system,BlinkMacSystemFont,sans-serif;background:#EEF2F9;padding:26px;display:flex;justify-content:center} .card{width:600px;max-width:100%;background:#FFFFFF;border:1px solid #E3E9F4;border-radius:20px;box-shadow:0 26px 64px -32px rgba(15,30,70,.34),0 2px 4px rgba(15,30,70,.05);overflow:hidden} .hdr{display:flex;align-items:center;gap:11px;padding:16px 20px;border-bottom:1px solid #EEF1F7;background:#F5F8FE} .hdr .ic{display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;border:2px solid #155DFC;border-radius:50%;color:#155DFC;font-size:15px;font-weight:800;flex-shrink:0} .hdr .t{min-width:0} .hdr .t .n{font-weight:800;font-size:14.5px;color:#0F172A;letter-spacing:-.2px} .hdr .t .s{font-size:12px;color:#64748B} .hdr .pill{margin-left:auto;display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;color:#155DFC;background:#E6EEFF;padding:5px 10px;border-radius:20px;white-space:nowrap} .hdr .pill .d{width:6px;height:6px;border-radius:50%;background:#155DFC;animation:pulseDot 2s infinite} .tabs{display:flex;gap:0;padding:12px 16px 0;background:#F5F8FE} .tab{flex:1;display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer;font-family:inherit;font-size:11.5px;font-weight:700;color:#64748B;background:transparent;border:none;border-bottom:2px solid transparent;padding:8px 4px 10px} .tab.on{font-weight:800;color:#155DFC;border-bottom-color:#155DFC} .tab .num{display:inline-flex;width:20px;height:20px;align-items:center;justify-content:center;border-radius:50%;font-size:11px;font-weight:800;color:#64748B;background:#EEF1F7} .tab.on .num{color:#fff;background:#155DFC} .divider{height:1px;background:#EEF1F7} .body{padding:20px} .eyebrow{font-size:10.5px;font-weight:800;letter-spacing:1.2px;text-transform:uppercase;color:#155DFC;margin-bottom:5px} .eyebrow.g{color:#15884F} .headline{font-family:'Inter',Georgia,serif;font-size:18.5px;font-weight:600;line-height:1.25;color:#0F172A;margin-bottom:12px} .lede{font-size:12.5px;line-height:1.55;color:#475569;margin:0 0 14px} .rows{display:flex;flex-direction:column;gap:8px;margin-bottom:14px} .row{display:flex;align-items:center;gap:11px;background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:11px 13px} .row .emoji{font-size:17px} .row .rt{flex:1;min-width:0} .row .rt .n{font-size:13px;font-weight:700;color:#0F172A} .row .rt .s{font-size:12px;color:#64748B} .pillsm{font-size:11px;font-weight:800;color:#155DFC;background:#E6EEFF;padding:4px 9px;border-radius:6px;flex-shrink:0} .pillsm.gray{font-weight:700;color:#64748B;background:#EEF1F7} /* chain / timeline */ .chainwrap{position:relative;padding-left:26px} .chainline{position:absolute;left:8px;top:8px;bottom:8px;width:2px;background:#E3E9F4} .cnode{position:relative;margin-bottom:14px} .cdot{position:absolute;left:-26px;top:4px;width:16px;height:16px;border-radius:50%;background:#fff;border:3px solid #94A3B8} .clabel{font-size:9.5px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:#64748B;margin-bottom:4px} .cbox{background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:10px 12px;font-size:12px;line-height:1.5;color:#334155} .cbox.graded{display:flex;align-items:flex-start;gap:9px;border-left-width:3px;border-left-style:solid} .cnote{margin:0 0 14px 4px;font-size:11px;line-height:1.5} .cnote .plus{display:inline-flex;width:16px;height:16px;align-items:center;justify-content:center;background:#155DFC;color:#fff;border-radius:4px;font-size:10px;font-weight:800;flex-shrink:0;margin-right:6px} .csummary{display:flex;align-items:center;gap:12px;background:#0A1B3D;border-radius:13px;padding:11px 15px;margin-top:4px} .csummary .t{flex:1;font-size:11.5px;color:#CBD8F5} .csummary .t b{color:#F1F5FF} /* matrix */ .mxwrap{border:1px solid #EEF1F7;border-radius:12px;overflow:hidden;margin-bottom:10px} .mxhead{display:grid;grid-template-columns:118px 1fr 1fr;background:#F5F8FE;border-bottom:1px solid #EEF1F7} .mxhead div{font-size:9px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:#64748B;padding:7px 9px} .mxrow{display:grid;grid-template-columns:118px 1fr 1fr;border-bottom:1px solid #EEF1F7} .mxrow:last-child{border-bottom:none} .mxrow>div{padding:9px;font-size:11.5px;line-height:1.4;color:#334155;display:flex;align-items:center;flex-wrap:wrap;gap:5px} .mxrow .mxlabel{font-weight:700;color:#0F172A;background:#FAFBFE} .mxchip{font-size:9px;font-weight:800;letter-spacing:.3px;text-transform:uppercase;padding:3px 6px;border-radius:5px;white-space:nowrap} .promptwrap{padding:0 20px 18px} .promptlbl{font-size:10px;font-weight:800;letter-spacing:1px;text-transform:uppercase;color:#94A3B8;margin-bottom:7px} .prompt{display:flex;align-items:flex-start;gap:9px;font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:11px;line-height:1.5;color:#1E293B;background:#F5F8FE;border:1px solid #EEF1F7;border-left:3px solid #155DFC;border-radius:9px;padding:11px 12px} .prompt .car{color:#155DFC;font-weight:800;flex-shrink:0} .flagrow{display:flex;align-items:flex-start;gap:10px;background:#F5F8FE;border:1px solid #EEF1F7;border-radius:11px;padding:10px 12px;border-left-width:3px;border-left-style:solid;margin-bottom:8px} .flagtag{font-size:9.5px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;padding:4px 8px;border-radius:5px;white-space:nowrap;flex-shrink:0} .flagtxt{font-size:12px;line-height:1.45;color:#334155} .lp{display:flex;align-items:center;gap:12px;background:#0A1B3D;border-radius:13px;padding:14px 16px;margin-top:6px} .lp .ic{display:inline-flex;width:34px;height:34px;align-items:center;justify-content:center;background:#14295C;border:1px solid #26407A;border-radius:9px;color:#7FA8FF;font-size:16px;flex-shrink:0} .lp .rt{flex:1;min-width:0} .lp .rt .n{font-size:13px;font-weight:800;color:#F1F5FF} .lp .rt .s{font-size:11.5px;color:#9DB2D9} .lp .open{font-size:11px;font-weight:800;color:#0A1B3D;background:#7FA8FF;padding:6px 11px;border-radius:7px;white-space:nowrap} </style> </head> <body> <div class="card"> <div class="hdr"> <span class="ic">&#9878;&#65039;</span> <div class="t"> <div class="n">Vista Workforce Collaborative · comparing cohorts without fooling yourself</div> <div class="s">DEMO-03 · Sopact Sense · Workforce Cohort</div> </div> <span class="pill"><span class="d"></span>Comparing</span> </div> <div class="tabs" id="tabs"></div> <div class="divider"></div> <div class="body" id="body"></div> <div class="promptwrap"> <div class="promptlbl">The prompt behind this step</div> <div class="prompt"><span class="car">&gt;</span><span id="promptTxt"></span></div> </div> </div> <script> (function(){ var TABS = ["Setup", "Compare", "Fix", "Report"]; var CONTENT = [{"eyebrow": "Step 1 · Load the dataset", "headline": "Clean data, persistent contact IDs, one Decision Brief.", "lede": "The Assistant works only from the Workforce Cohort dataset (DEMO-03 · Vista Workforce Collaborative) already loaded in Sopact Sense — nothing outside the record.", "prompt": "You are the Sopact Sense Assistant working over the [DEMO] dataset (clean data + persistent contact IDs). Load my Decision Brief (decision, audience, outcomes, indicators, evidence standard) first, then wait for my task."}, {"eyebrow": "Step 2 · Benchmark the cohorts", "headline": "Normalise for size and program length before comparing deltas.", "lede": "Every cohort reading is graded <strong style=\"color:#15884F\">green</strong>, <strong style=\"color:#C9820A\">amber</strong>, <strong style=\"color:#C63E2B\">red</strong>.", "prompt": "Benchmark cohorts [COHORTS] on [METRICS], normalising for size and program length; report deltas + confounds. Grade green/amber/red."}, {"eyebrow": "Step 3 · One-fix follow-up", "headline": "Control the confound.", "lede": "The Assistant takes the lowest-graded element — 2024's lower gain, confounded by program length — and names the single indicator that would move it to green.", "prompt": "Take the lowest-graded element above and fix it using only what the program could realistically measure. Show the before → after grade and the single indicator/edit that moves it to green."}, {"eyebrow": "Step 4 · Missing & incomplete report", "headline": "Longitudinal — Cohort Comparison Report", "lede": "Every amber or red item becomes one named ask — the report leads with the decision it informs.", "prompt": "Create a 'missing & incomplete' report from this analysis in Sopact branding [or paste your website URL / brand guideline to apply your own]. List every element graded amber or red, what is missing, and the one input that fixes each. Lead with the decision this report informs."}]; var BODIES = { setup: "<div class=\"row\"><span class=\"emoji\">&#128221;</span><div class=\"rt\"><div class=\"n\">Representative contact (pre → post)</div><div class=\"s\">Contact L-2023-001 (Downtown) · confidence 2→5, skill 24→78, employed within 6 months</div></div><span class=\"pillsm\">Pasted</span></div><div class=\"row\"><span class=\"emoji\">&#128203;</span><div class=\"rt\"><div class=\"n\">DEMO-03 · Workforce Cohort</div><div class=\"s\">9 Questions · 55 Responses · Active</div></div><span class=\"pillsm gray\">Structure</span></div><div class=\"row\"><span class=\"emoji\">&#128274;</span><div class=\"rt\"><div class=\"n\">No hallucination rule</div><div class=\"s\">Only what the program states; infer = flagged</div></div><span class=\"pillsm gray\">Required</span></div>", build: "<div class=\"mxwrap\"><div class=\"mxhead\"><div></div><div>Skill gain</div><div>Confound</div></div><div class=\"mxrow\"><div class=\"mxlabel\">2023</div><div>+38<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>full 12-week program</div></div><div class=\"mxrow\"><div class=\"mxlabel\">2024</div><div>+31<span class=\"mxchip\" style=\"background:#C9820A;color:#fff\">AMBER</span></div><div>shorter program window</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Comparison</div><div>delta -7</div><div>not real decline — confounded<span class=\"mxchip\" style=\"background:#C63E2B;color:#fff\">RED</span></div></div></div>", fix: "<div class=\"mxwrap\"><div class=\"mxhead\"><div></div><div>Skill gain</div><div>Confound</div></div><div class=\"mxrow\"><div class=\"mxlabel\">2023</div><div>+38<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>full 12-week program</div></div><div class=\"mxrow\"><div class=\"mxlabel\">2024</div><div>GREEN · comparable<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>shorter program window</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Comparison</div><div>delta -7</div><div>not real decline — confounded<span class=\"mxchip\" style=\"background:#C63E2B;color:#fff\">RED</span></div></div></div><div class=\"cnote\" style=\"color:#15884F;margin-left:0\"><span class=\"plus\">+</span><strong>Fix applied:</strong> Normalise gain per program-week before comparing</div>", reportFlags: "<div class=\"flagrow\" style=\"border-left-color:#C9820A\"><span class=\"flagtag\" style=\"color:#C9820A;background:#FBF0DA\">AMBER</span><div class=\"flagtxt\">2024 cohort&#x27;s lower raw gain is confounded by a shorter program window, not a weaker effect.</div></div><div class=\"flagrow\" style=\"border-left-color:#C63E2B\"><span class=\"flagtag\" style=\"color:#C63E2B;background:#FCE9E7\">RED</span><div class=\"flagtxt\">The raw delta of -7 reads as a decline, but it is confounded by program length, not a real drop.</div></div>", lpTitle: "Missing & incomplete report · shareable link", lpSub: "Decision-first · Sopact branding · Vista Workforce Collaborative · comparing cohorts without fooling yourself", summaryBefore: "Grade: 1 green &middot; 1 amber &middot; 1 red. Raw delta reads as a -7 decline for 2024 — but the program window was shorter", summaryAfter: "Grade: 2 green &middot; 0 amber &middot; 1 red. 2024's gain moves from confounded to comparable once normalised per program-week" }; var phase = 1; var tabsEl = document.getElementById('tabs'); var bodyEl = document.getElementById('body'); var promptEl = document.getElementById('promptTxt'); function renderTabs(){ tabsEl.innerHTML = ''; TABS.forEach(function(label, i){ var b = document.createElement('button'); b.type = 'button'; b.className = 'tab' + (i === phase ? ' on' : ''); b.innerHTML = '<span class="num">' + (i+1) + '</span><span>' + label + '</span>'; b.addEventListener('click', function(){ phase = i; render(); }); tabsEl.appendChild(b); }); } function renderBody(){ var c = CONTENT[phase]; var eyebrowClass = (phase===2) ? 'eyebrow g' : 'eyebrow'; var out = '<div class="' + eyebrowClass + '">' + c.eyebrow + '</div><div class="headline">' + c.headline + '</div><p class="lede">' + c.lede + '</p>'; if (phase === 0) { out += '<div class="rows">' + BODIES.setup + '</div>'; } else if (phase === 1) { out += BODIES.build; out += '<div class="csummary"><div class="t"><b>' + BODIES.summaryBefore + '</b></div></div>'; } else if (phase === 2) { out += BODIES.fix; out += '<div class="csummary"><div class="t"><b>' + BODIES.summaryAfter + '</b></div></div>'; } else { out += BODIES.reportFlags; out += '<div class="lp"><span class="ic">&#128196;</span><div class="rt"><div class="n">' + BODIES.lpTitle + '</div><div class="s">' + BODIES.lpSub + '</div></div><span class="open">Open &rarr;</span></div>'; } bodyEl.innerHTML = out; promptEl.textContent = c.prompt; } function render(){ renderTabs(); renderBody(); } render(); })(); </script> </body> </html>

In short: Before you compare two cohorts, check what changed in how you measured them. Benchmark both on the same metrics, normalise for cohort size and program length, name every confound that could explain the gap, and grade the comparison green, amber, or red — so a raw delta is never mistaken for a real improvement.

1 · Set up over your data

Start where both cohorts live in one clean dataset. This walkthrough uses DEMO-03 · Workforce Cohort — Vista Workforce Collaborative, with a 2023 and a 2024 cohort and persistent IDs. Load your Decision Brief first so the comparison is framed by the decision it informs.

You are the Sopact Sense Assistant working over the DEMO-03 · Workforce Cohort dataset (clean data + persistent contact IDs). Load my Decision Brief (decision, audience, outcomes, indicators, evidence standard) first, then wait for my task.

2 · Write the comparison prompt

The prompt benchmarks the cohorts and forces the confounds into the open.

Benchmark cohorts [COHORTS] on [METRICS], normalising for size and program length; report deltas + confounds. Grade green/amber/red.

Five elements keep it honest: the dataset holding both cohorts, the normalise step for size and program length, the confounds that could explain a gap, the rule that delta≠improvement until confounds are ruled out, and the grade G/A/R on how trustworthy the comparison is.

3 · What Sense produces

Run on the Workforce Cohort dataset (DEMO 03) already loaded in Sopact Sense.

GRADE: green | 2023 baseline | solid, well-measured; amber | 2024 window | shorter program length; red | Raw delta | confounded by cohort and window

The grade tells you how much the gap is worth. Green means a clean reference — the 2023 baseline is well measured and comparable. Amber means a normalisation issue — the 2024 cohort ran a shorter window, so its outcomes need adjusting before comparison. Red means the headline number is confounded — the raw delta mixes a real effect with cohort and window differences, so reporting it as improvement would mislead.

4 · Turn a weak link green

Fix the confounded comparison with the smallest realistic change.

Take the lowest-graded element above and fix it using only what the program could realistically measure. Show the before → after grade and the single indicator/edit that moves it to green.

5 · Make the report and share

Produce a branded "missing & incomplete" report and a shareable link.

Create a 'missing & incomplete' report from this analysis in Sopact branding [or paste your website URL / brand guideline to apply your own]. List every element graded amber or red, what is missing, and the one input that fixes each. Lead with the decision this report informs.
Create a shareable link for this report and open it in a new tab.

Tricks, tips, and troubleshooting

Check measurement before you compare. If the survey, timing, or population changed between cohorts, the gap may be an artefact of how you measured, not what happened.

Normalise size and length first. A bigger or longer-running cohort will look different for reasons that have nothing to do with program quality. Adjust for both before reading the delta.

Name the confounds out loud. A confound you've written down is one a reader can weigh. A confound you've ignored quietly turns a delta into a false claim.

Report the delta with caveats, not as a verdict. Until confounds are ruled out, a delta is a question, not an improvement.

List every confound between these two cohorts and, for each, whether it inflates or deflates the raw delta.

Frequently asked questions

How do I compare outcomes between two cohorts?

Benchmark both cohorts on the same metrics, normalise for differences in size and program length, then report the delta alongside every confound that could explain it. The goal is to separate a genuine program effect from differences in who was in each cohort and how long they were measured — and to grade how confident you can be in the comparison.

What is a confound, and why does it matter here?

A confound is any factor that differs between the cohorts and could move the outcome on its own — a shorter program window, a different intake mix, a changed survey question. It matters because it offers a rival explanation for the gap, so an unacknowledged confound can turn a measurement artefact into a claimed improvement.

Why isn't a raw delta the same as an improvement?

A raw delta only tells you the two cohorts scored differently, not why. Until you've normalised for size and length and ruled out confounds, that difference could come from the program, the people, or the measurement — so reporting it as improvement overstates what the data supports.

Ready to try it for yourself?

Open Sopact Sense, paste your program description, and put it to work.

Try in Sopact