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

Analyze Survey Results by Demographic Subgroup

Averages hide who is being left behind. This walks through disaggregating an outcome by subgroup in Sopact Sense, grading each cut, and finding the one input that makes a weak subgroup result reportable.

<!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">&#128202;</span> <div class="t"> <div class="n">Vista Workforce Collaborative · Disaggregate Outcomes</div> <div class="s">DEMO-03 · Sopact Sense · Survey Analysis</div> </div> <span class="pill"><span class="d"></span>Disaggregating</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", "Disaggregate", "Fix", "Report"]; var CONTENT = [{"eyebrow": "Step 1 · Load the Decision Brief", "headline": "Equity lives in the disaggregation, not the average.", "lede": "The Assistant works only from the Workforce Cohort dataset (DEMO-03) — Vista Workforce Collaborative.", "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 · Break the outcome down by subgroup", "headline": "Who's being left behind?", "lede": "Change per subgroup and gap to mean, graded <strong style=\"color:#15884F\">green</strong>, <strong style=\"color:#C9820A\">amber</strong>, <strong style=\"color:#C63E2B\">red</strong> on strength and sample size.", "prompt": "Break [METRIC] change for [COHORT] by [DIMENSIONS]: change per subgroup, gap to mean; flag left-behind; small-n caution. Grade green/amber/red."}, {"eyebrow": "Step 3 · One-fix follow-up", "headline": "Act on the gap.", "lede": "East site sits well below the mean — left behind on the outcome. The Assistant names the single data point that moves 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": "The East site is being left behind.", "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\">Decision Brief</div><div class=\"s\">Decision, audience, outcomes, indicators, evidence standard loaded first</div></div><span class=\"pillsm\">Pasted</span></div><div class=\"row\"><span class=\"emoji\">&#128203;</span><div class=\"rt\"><div class=\"n\">Five elements</div><div class=\"s\">Dataset · by subgroup · gap to mean · small-n caution · grade G/A/R</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>Change</div><div>Gap to Mean</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Downtown</div><div>+40<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>+7</div></div><div class=\"mxrow\"><div class=\"mxlabel\">North</div><div>+33</div><div>—</div></div><div class=\"mxrow\"><div class=\"mxlabel\">East</div><div>+8<span class=\"mxchip\" style=\"background:#C63E2B;color:#fff\">RED</span></div><div>-25 — left behind</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Nonbinary (n=4)</div><div>small-n — caution<span class=\"mxchip\" style=\"background:#C9820A;color:#fff\">AMBER</span></div><div></div></div></div>", fix: "<div class=\"mxwrap\"><div class=\"mxhead\"><div></div><div>Change</div><div>Gap to Mean</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Downtown</div><div>+40<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>+7</div></div><div class=\"mxrow\"><div class=\"mxlabel\">North</div><div>+33</div><div>—</div></div><div class=\"mxrow\"><div class=\"mxlabel\">East</div><div>+8<span class=\"mxchip\" style=\"background:#C63E2B;color:#fff\">RED</span></div><div>-25 — left behind</div></div><div class=\"mxrow\"><div class=\"mxlabel\">Nonbinary (n=4)</div><div>small-n — caution<span class=\"mxchip\" style=\"background:#15884F;color:#fff\">GREEN</span></div><div>Investigate East-site delivery; targeted support</div></div></div><div class=\"cnote\" style=\"color:#15884F;margin-left:0\"><span class=\"plus\">+</span><strong>Fix applied:</strong> Investigate East-site delivery; add targeted support — moves East site from AMBER (left behind on the outcome) to GREEN (gap addressed).</div>", reportFlags: "<div class=\"flagrow\" style=\"border-left-color:#C9820A\"><span class=\"flagtag\" style=\"color:#C9820A;background:#FBF0DA\">AMBER</span><div class=\"flagtxt\">Nonbinary subgroup: n=4, too small to claim. Fix: report with a small-n caveat.</div></div><div class=\"flagrow\" style=\"border-left-color:#C63E2B\"><span class=\"flagtag\" style=\"color:#C63E2B;background:#FCE9E7\">RED</span><div class=\"flagtxt\">East site: +8 vs +33 mean. Fix: investigate delivery; add targeted support.</div></div>", lpTitle: "Missing & incomplete report · shareable link", lpSub: "Decision-first · Sopact branding · Vista Workforce Collaborative · Disaggregate Outcomes", summaryBefore: "Grade: 1 green &middot; 1 amber &middot; 1 red. average hides who's behind", summaryAfter: "Grade: 2 green &middot; 0 amber &middot; 1 red. East site named, support targeted" }; 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: A single average can look healthy while one subgroup quietly falls behind. In Sopact Sense you disaggregate the outcome by subgroup, see the gap to the mean for each cut, and grade every cut green, amber, or red — so equity shows up in the data instead of hiding in the average.

1 · Set up over your data

Point the Assistant at a clean dataset with persistent contact IDs so every response stays tied to one person across the cohort. Load your Decision Brief first — the decision, the audience, the outcome, the indicator, and your evidence standard — so the disaggregation answers a real reporting question rather than slicing data for its own sake.

2 · Write the prompt

Break [METRIC] change for [COHORT] by [DIMENSIONS]: change per subgroup, gap to mean; flag left-behind; small-n caution. Grade green/amber/red.

The prompt carries five elements. The dataset is the loaded cohort. By subgroup names the demographic dimensions you cut on. Gap to mean measures each subgroup against the cohort average. Small-n caution tells the model to flag any cut too thin to report. Grade G/A/R forces a green, amber, or red verdict on each cut so you can act.

3 · What Sense produces

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

GRADE: green | 1 | Strong subgroup; amber | 1 | Small-n subgroup; red | 1 | Left-behind East site

Sense returns a graded cut for each subgroup. A well-evidenced subgroup comes back green. A subgroup resting on too few responses comes back amber — the result might be real, but it cannot be reported with confidence. The site sitting well below the cohort mean with no explanation comes back red: that is the group being left behind.

4 · Turn a weak link green

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.

For the left-behind East site, the fix is small: add a short why-question at exit for East-site participants. That single indicator turns an unexplained red gap into an evidenced amber you can act on — and eventually a green you can report.

5 · Make the report and share it

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

Decide your small-n floor first. Set a minimum subgroup size before you run the cut, so the model flags thin groups consistently instead of you deciding case by case after the fact.

Gap to mean beats raw scores. A subgroup can post a decent number and still trail the cohort badly. Always read each cut against the mean, not on its own.

Don't over-slice. Cutting by five dimensions at once produces dozens of tiny, unreportable cells. Pick the two or three dimensions tied to your decision.

Pool before you bury. A thin subgroup isn't useless.

Pool it with an adjacent cycle or report it as indicative, not conclusive — then collect more before the next report.

Frequently asked questions

How do you analyze survey results by demographic subgroup?

Disaggregate the outcome by the dimensions that matter to your decision, measure each subgroup's gap to the cohort mean, flag any cut too small to report, and grade each one green, amber, or red. Sopact Sense does this in one prompt over a clean dataset with persistent contact IDs.

What is a small-n subgroup and why does it get flagged amber?

A small-n subgroup is a cut with too few responses to report confidently. It is graded amber because the result may be real but cannot stand on its own — you either pool it with another cycle or label it indicative until you collect more.

How do I know which subgroup is being left behind?

Read each subgroup's gap to the cohort mean. The group sitting well below the mean with no explanation is the left-behind one — and the fix is usually a single why-question added at exit for that group.

Ready to try it for yourself?

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

Try in Sopact