Statistics and experimentation skill 03 of 6

Sample size calculation

Sample size calculation works out how many users each group of a test needs, and how long to run it, before you launch. This skill makes an AI agent compute the figure from the baseline, the effect you want to detect, the significance level and the power, then validate it, because popular calculators and tables are often several times wrong.

sample-size-calculation/SKILL.md, version 1.0.0, about 2,500 words.

Download .mdSkill folder (.zip)

When to use this, and when not to

Use this skill before an experiment runs, to decide how many observations each group needs and how long the test must stay live. The triggers are "how many users do I need", "what sample size for this A/B test", "how long to run it", "power analysis", "minimum detectable effect", or "can this traffic detect the lift I care about". The work is to turn a baseline, a target effect, a significance level and a power target into a per-group sample size and a run time, and to check that number is right.

Do not use it to read a test that has already finished; that is ab-test-analysis. Do not use it to run the significance test itself; that is hypothesis-testing. And do not use it to compute "observed power" from the result of a completed test: post-hoc power is a function of the p-value and adds nothing, so it should not be reported (Hoenig and Heisey, 2001). Power analysis belongs before the data, not after.

The core idea: a test that is too small cannot find the effect you care about, so a flat result tells you nothing. The sample size is set by four numbers fixed in advance, the baseline, the minimum detectable effect, the significance level and the power, and the single most common way the figure comes out wrong is confusing an absolute effect with a relative one. Many published calculators and skills ship sample-size tables that are two to ten times off, so this skill computes the number from the formula and then validates it.

Inputs the agent must have before starting

  1. The metric type and its baseline. For a proportion, the baseline conversion rate. For a continuous metric, the baseline mean and its standard deviation (sample size for means cannot be computed without the standard deviation).
  2. The minimum detectable effect (MDE), and whether it is absolute or relative. A 10% relative lift on a 5% baseline is 0.5 percentage points (to 5.5%); a 10 percentage point absolute lift is to 15%. These give wildly different sample sizes, so make the agent confirm which one is meant.
  3. The significance level, alpha. Default 0.05, two-sided. Use one-sided only when the direction is committed in advance.
  4. The power, one minus the Type II error rate. Default 0.80; use 0.90 for a high-stakes or hard-to-rerun test. Higher power needs more data.
  5. The number of variants, including control. More than two means the alpha should be split across comparisons (see hypothesis-testing), which raises the sample size.
  6. The daily eligible traffic and the share exposed to the test, to convert the sample size into a run time.

If the MDE basis (absolute or relative), the standard deviation for a continuous metric, or the eligible traffic is missing, ask. A sample size computed on a guessed MDE basis is not an estimate, it is a wrong answer.

Raw SKILL.md file

.md

This is the exact file agents read, including the credit header and licence notice. Save it as sample-size-calculation/SKILL.md.

---
name: sample-size-calculation
description: >
  Work out how many observations per group an experiment needs, and how long to run it, before launch, from the baseline rate or mean, the minimum detectable effect, the significance level and the power. Covers the correct two-proportion and two-means formulas, absolute versus relative MDE, alpha and power defaults, one versus two-sided tests, adjusting for several variants, converting a sample size into a run time over full business cycles, and a validator that recomputes power so a wrong number is caught. Use it for "how many users do I need", "sample size for my A/B test", "how long should I run this test", "power analysis", "minimum detectable effect", "is my test big enough", or "what lift can I detect with this traffic". Do NOT use it to analyse a finished test (see ab-test-analysis), to run the significance test itself (see hypothesis-testing), or to compute observed power after the fact, which is not meaningful.
license: Free to use and adapt under CC BY 4.0, with credit to Afeez Adebayo. Link afeezadebayo.com, https://www.linkedin.com/in/afeez-adebayo/ and this skill's page at https://afeezadebayo.com/skills-md/data/statistics-experimentation/sample-size-calculation/.
---

# Sample size calculation

## When to use this, and when not to

Use this skill before an experiment runs, to decide how many observations each group needs and how long the test must stay live. The triggers are "how many users do I need", "what sample size for this A/B test", "how long to run it", "power analysis", "minimum detectable effect", or "can this traffic detect the lift I care about". The work is to turn a baseline, a target effect, a significance level and a power target into a per-group sample size and a run time, and to check that number is right.

Do not use it to read a test that has already finished; that is `ab-test-analysis`. Do not use it to run the significance test itself; that is `hypothesis-testing`. And do not use it to compute "observed power" from the result of a completed test: post-hoc power is a function of the p-value and adds nothing, so it should not be reported (Hoenig and Heisey, 2001). Power analysis belongs before the data, not after.

The core idea: a test that is too small cannot find the effect you care about, so a flat result tells you nothing. The sample size is set by four numbers fixed in advance, the baseline, the minimum detectable effect, the significance level and the power, and the single most common way the figure comes out wrong is confusing an absolute effect with a relative one. Many published calculators and skills ship sample-size tables that are two to ten times off, so this skill computes the number from the formula and then validates it.

## Inputs the agent must have before starting

1. The metric type and its baseline. For a proportion, the baseline conversion rate. For a continuous metric, the baseline mean and its standard deviation (sample size for means cannot be computed without the standard deviation).
2. The minimum detectable effect (MDE), and whether it is absolute or relative. A 10% relative lift on a 5% baseline is 0.5 percentage points (to 5.5%); a 10 percentage point absolute lift is to 15%. These give wildly different sample sizes, so make the agent confirm which one is meant.
3. The significance level, alpha. Default 0.05, two-sided. Use one-sided only when the direction is committed in advance.
4. The power, one minus the Type II error rate. Default 0.80; use 0.90 for a high-stakes or hard-to-rerun test. Higher power needs more data.
5. The number of variants, including control. More than two means the alpha should be split across comparisons (see `hypothesis-testing`), which raises the sample size.
6. The daily eligible traffic and the share exposed to the test, to convert the sample size into a run time.

If the MDE basis (absolute or relative), the standard deviation for a continuous metric, or the eligible traffic is missing, ask. A sample size computed on a guessed MDE basis is not an estimate, it is a wrong answer.

## The workflow, step by step

### 1. Pin the metric and the MDE in the metric's own units

Write the baseline and the target value explicitly. For a proportion, state both as rates: baseline 5%, target 5.5% (a 10% relative lift). For a mean, state the baseline, the standard deviation and the absolute change you want to detect. Converting the MDE to the metric's own units here is what stops the absolute-versus-relative error later.

### 2. Set alpha, power and sidedness, and adjust for variants

Default to alpha 0.05 two-sided and power 0.80. Raise power to 0.90 when a wrong "no effect" is expensive. For k variants against one control, there are k comparisons, so divide alpha by k (Bonferroni) before computing the size; this raises the per-group number, which is the honest cost of testing more variants at once.

### 3. Compute the per-group sample size with the correct formula

For two proportions, per group:

n = (z<sub>1-alpha/2</sub> + z<sub>1-beta</sub>)^2 * (p1(1-p1) + p2(1-p2)) / (p2 - p1)^2

For two means, per group:

n = 2 * (z<sub>1-alpha/2</sub> + z<sub>1-beta</sub>)^2 * sigma^2 / delta^2

Compute it with a power library rather than by hand, because the library handles the effect-size transform and the exact quantiles (see the templates). As a sanity check, Evan Miller's rule of thumb is n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, which for a standardised effect size d is about 16 / d^2 (Evan Miller, 2010). If the library answer and the rule of thumb disagree by more than roughly 20%, something in the inputs is wrong.

### 4. Validate the number before you trust it

Recompute the power at the sample size you got; it should come back at the power you asked for. Then compare against a second source (a reputable calculator or the reference table below). If a calculator or an existing skill gives a number more than about 10% away, do not average them: find out why, because popular sample-size tables are frequently two to ten times wrong, usually from an absolute-versus-relative MDE mix-up or a dropped power term. The validator in the templates does this check in code.

Correct per-group sizes for a two-sided test at alpha 0.05 and 80% power (computed, not quoted):

| Baseline | Relative MDE | Target | Per group |
|---|---|---|---|
| 5% | +10% | 5.5% | about 31,000 |
| 5% | +20% | 6.0% | about 8,100 |
| 10% | +10% | 11.0% | about 14,700 |
| 10% | +15% | 11.5% | about 6,700 |
| 20% | +10% | 22.0% | about 6,500 |

### 5. Turn the sample size into a run time, with a floor and a ceiling

Days needed is the total sample (per-group size times the number of groups) divided by the daily eligible users times the share exposed:

days = (n_per_group * groups) / (daily_eligible * share_exposed)

Then apply two rules. Floor: run for at least one full business cycle, and preferably two, even if the sample is reached sooner, so weekday and weekend behaviour are both captured (Optimizely; Kohavi). Ceiling: beyond about four to six weeks, novelty effects and population drift start to distort the result, so a test that needs longer than that is a signal to change the design, not to wait.

### 6. If the traffic cannot support the test, change the design

If the honest run time is longer than about eight weeks, the test as specified is not feasible. The levers, in order of preference: accept a larger MDE (detect a bigger effect), reduce the number of variants, choose a higher-signal metric (one closer to the change, with more events per user), or fall back to a qualitative method. Report the trade-off rather than quietly running an underpowered test.

## Worked example, end to end

A team wants to test a new pricing page. The baseline checkout conversion is 5%, and the smallest lift worth shipping is a 10% relative rise, to 5.5%. They will use alpha 0.05 two-sided and 80% power, with one control and one variant, split 50/50.

```python
import math
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
p1, p2 = 0.05, 0.055                       # baseline and target (relative +10%)
es = proportion_effectsize(p2, p1)          # Cohen's h
n = NormalIndPower().solve_power(es, alpha=0.05, power=0.80,
                                 ratio=1, alternative="two-sided")
print(math.ceil(n))                         # 31218 per group
```

The answer is about 31,218 per group, so about 62,436 users in total. A popular A/B planning skill lists roughly 19,000 per variant for a 5% baseline at a 20% MDE; the correct figure for 5% at a 20% relative MDE is about 8,100, so that table is more than twice too high, which would waste weeks of traffic. With 5,000 eligible users a day at full exposure, the run time is 62,436 / 5,000, about 13 days, which the two-week business-cycle floor rounds to 14 days. The output is: 31,218 per group, run for 14 days, powered to detect a lift from 5% to 5.5% at 80% power and 95% confidence, with the assumptions stated so no one later mistakes the floor for the earliest honest stop.

## Templates you can use verbatim

```python
# Proportions: sample size per group, then validate the power
import math
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
def n_proportion(p1, mde_rel, alpha=0.05, power=0.80, k_variants=1):
    p2 = p1 * (1 + mde_rel)                              # relative MDE
    alpha_adj = alpha / max(1, k_variants)              # Bonferroni for >1 variant
    es = proportion_effectsize(p2, p1)
    an = NormalIndPower()
    n = an.solve_power(es, alpha=alpha_adj, power=power, ratio=1,
                       alternative="two-sided")
    check = an.power(es, nobs1=math.ceil(n), alpha=alpha_adj,
                     ratio=1, alternative="two-sided")  # should ~= power
    return {"n_per_group": math.ceil(n), "achieved_power": round(check, 3)}
```

```python
# Means: per group from baseline sd and an absolute delta
import math
from statsmodels.stats.power import TTestIndPower
def n_means(sigma, delta, alpha=0.05, power=0.80):
    d = delta / sigma                                   # standardised effect
    n = TTestIndPower().solve_power(effect_size=d, alpha=alpha, power=power,
                                    ratio=1, alternative="two-sided")
    return math.ceil(n)
```

```text
Run-time and feasibility check
total = n_per_group * number_of_groups
days  = total / (daily_eligible * share_exposed)
floor = max(days, 7)            # one business cycle, prefer 14
if days > 56:  change the design (bigger MDE, fewer variants, higher-signal metric)
report: n_per_group, total, days (>= floor), alpha, power, MDE basis, assumptions
```

## Failure modes and anti-patterns

1. **Absolute versus relative MDE mix-up.** A 10% lift on a 5% baseline is 0.5 points, not 10 points; getting this wrong moves the sample size by orders of magnitude. Spot it by stating the baseline and target as explicit values. Fix: confirm the basis before computing.
2. **Trusting a calculator or table without checking.** Many published tables are two to ten times off. Spot it by recomputing the power at the suggested n, or comparing to the reference table here. Fix: use the validator; investigate any gap over about 10%.
3. **Dropping the power term.** A formula with only the alpha quantile (missing z for beta) understates the sample size and leaves the test underpowered. Spot it when the number looks suspiciously small. Fix: use a power library, which includes both terms.
4. **Ignoring the business-cycle floor.** Hitting the sample in three days and stopping misses weekend behaviour. Spot it from a run time under a week. Fix: run at least one full cycle, preferably two, whatever the maths says.
5. **Post-hoc power.** Computing power from the observed effect after the test is circular and uninformative. Spot it when "observed power" is quoted to defend a null result. Fix: report the confidence interval instead (see `ab-test-analysis`), and never compute power after the fact.

## Quality bar

- The baseline, the MDE and its basis (absolute or relative), alpha, power and sidedness are all stated before the number is computed.
- The sample size is computed with a power library, cross-checked against the rule of thumb, and validated by recomputing the achieved power.
- Any disagreement over about 10% with another calculator is explained, not averaged away.
- The run time applies a business-cycle floor of at least one week (prefer two) and flags a test that would need more than about eight weeks.
- Multiple variants split alpha, and the higher sample size that follows is reported, not hidden.
- Post-hoc power is never reported; a finished test is read with a confidence interval instead.

## Data handling and safety

Sample-size work uses summary numbers (a baseline rate, a standard deviation, a traffic figure), so it rarely touches personal data; if a baseline is estimated from raw records, do not log or send those records, compute the summary in place. The output sizes a test, it does not launch one: deciding to run an experiment, allocate traffic or delay a release is a human call, and this skill produces a plan, not an action. Never fabricate a baseline, a standard deviation or a traffic figure to make a test look feasible; if an input is missing, ask for it or label the result as conditional on an assumption. When the test informs a decision about money, health, legal standing or employment, an underpowered test can do real harm by missing a true effect, so state the power and the smallest effect the test can detect, and let a human weigh whether that is enough.

## Appendix: tool-specific notes (verify before relying on these)

- **statsmodels:** `NormalIndPower().solve_power(effect_size, alpha, power, ratio, alternative)` for proportions with `proportion_effectsize(p2, p1)` giving Cohen's h; `TTestIndPower().solve_power(effect_size=d, ...)` for means with d = delta / sigma; `GofChisquarePower` for chi-square designs. `solve_power` leaves exactly one of `effect_size`, `nobs1`, `alpha` or `power` as None and solves for it, so you can also solve for the detectable effect given a fixed sample. Recompute `power(...)` at the rounded n to validate.
- **Evan Miller's calculator and rule of thumb:** n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, a quick sanity check; his online tool is a reputable second source. Verify its MDE basis matches yours.
- **Optimizely and VWO:** their sequential Stats Engine does not require a fixed sample size in advance, but a planning estimate still helps; their calculators default to a relative MDE and a baseline, so confirm the basis when comparing. Treat their duration estimates as specific to their sequential method.
- **R:** `power.prop.test(p1, p2, power, sig.level)` and `power.t.test(delta, sd, power, sig.level)` in base R, and the `pwr` package (`pwr.2p.test`, `pwr.t.test`) using Cohen's effect sizes. R's functions take the effect directly, so state p1 and p2 in their own units.
- **G*Power:** a trusted desktop tool for cross-checking; match the test family, the tails and the effect-size input exactly, or its answer will differ from the library's.

## Sources

- statsmodels documentation, `statsmodels.stats.power` (`NormalIndPower`, `TTestIndPower`, `solve_power`, `power`) and `proportion_effectsize`: the solve-for-one-parameter design, the effect-size inputs, and recomputing power to validate. Verified 7 November 2026.
- Evan Miller, "How Not To Run an A/B Test" and "Sample Size Calculator" (2010): the rule of thumb n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, and that committing to a sample size in advance is what keeps the significance level honest. Verified 7 November 2026.
- Optimizely documentation, "How long to run an experiment" and the sample size calculator: the default relative MDE and baseline inputs, that higher baselines need smaller samples, that high-variance metrics need more data, and the at-least-one-business-cycle rule. Verified 7 November 2026.
- Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments* (2020): that effects are usually small (so MDEs must be realistic), that tests should cover full business cycles, and the cost of underpowered experiments. Verified 7 November 2026.
- Hoenig and Heisey, "The Abuse of Power: The Pervasive Fallacy of Power Calculations for Data Analysis" (The American Statistician, 2001): that observed or post-hoc power is a function of the p-value and should not be used to interpret a completed test. Verified 7 November 2026.
- Existing skills reviewed and improved on: the `mohitagw15856` ab-test-planner and `openclaudia` ab-test-setup skills both publish sample-size lookup tables that do not match their own stated formulas, off by factors of roughly two to ten; this skill computes the figure from a power library, ships a validator that recomputes the achieved power, and gives a corrected reference table. Verified 7 November 2026.

The workflow, step by step

1. Pin the metric and the MDE in the metric's own units

Write the baseline and the target value explicitly. For a proportion, state both as rates: baseline 5%, target 5.5% (a 10% relative lift). For a mean, state the baseline, the standard deviation and the absolute change you want to detect. Converting the MDE to the metric's own units here is what stops the absolute-versus-relative error later.

2. Set alpha, power and sidedness, and adjust for variants

Default to alpha 0.05 two-sided and power 0.80. Raise power to 0.90 when a wrong "no effect" is expensive. For k variants against one control, there are k comparisons, so divide alpha by k (Bonferroni) before computing the size; this raises the per-group number, which is the honest cost of testing more variants at once.

3. Compute the per-group sample size with the correct formula

For two proportions, per group:

n = (z<sub>1-alpha/2</sub> + z<sub>1-beta</sub>)^2 * (p1(1-p1) + p2(1-p2)) / (p2 - p1)^2

For two means, per group:

n = 2 * (z<sub>1-alpha/2</sub> + z<sub>1-beta</sub>)^2 * sigma^2 / delta^2

Compute it with a power library rather than by hand, because the library handles the effect-size transform and the exact quantiles (see the templates). As a sanity check, Evan Miller's rule of thumb is n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, which for a standardised effect size d is about 16 / d^2 (Evan Miller, 2010). If the library answer and the rule of thumb disagree by more than roughly 20%, something in the inputs is wrong.

4. Validate the number before you trust it

Recompute the power at the sample size you got; it should come back at the power you asked for. Then compare against a second source (a reputable calculator or the reference table below). If a calculator or an existing skill gives a number more than about 10% away, do not average them: find out why, because popular sample-size tables are frequently two to ten times wrong, usually from an absolute-versus-relative MDE mix-up or a dropped power term. The validator in the templates does this check in code.

Correct per-group sizes for a two-sided test at alpha 0.05 and 80% power (computed, not quoted):

BaselineRelative MDETargetPer group
5%+10%5.5%about 31,000
5%+20%6.0%about 8,100
10%+10%11.0%about 14,700
10%+15%11.5%about 6,700
20%+10%22.0%about 6,500

5. Turn the sample size into a run time, with a floor and a ceiling

Days needed is the total sample (per-group size times the number of groups) divided by the daily eligible users times the share exposed:

days = (n_per_group * groups) / (daily_eligible * share_exposed)

Then apply two rules. Floor: run for at least one full business cycle, and preferably two, even if the sample is reached sooner, so weekday and weekend behaviour are both captured (Optimizely; Kohavi). Ceiling: beyond about four to six weeks, novelty effects and population drift start to distort the result, so a test that needs longer than that is a signal to change the design, not to wait.

6. If the traffic cannot support the test, change the design

If the honest run time is longer than about eight weeks, the test as specified is not feasible. The levers, in order of preference: accept a larger MDE (detect a bigger effect), reduce the number of variants, choose a higher-signal metric (one closer to the change, with more events per user), or fall back to a qualitative method. Report the trade-off rather than quietly running an underpowered test.

Worked example, end to end

A team wants to test a new pricing page. The baseline checkout conversion is 5%, and the smallest lift worth shipping is a 10% relative rise, to 5.5%. They will use alpha 0.05 two-sided and 80% power, with one control and one variant, split 50/50.

import math
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
p1, p2 = 0.05, 0.055                       # baseline and target (relative +10%)
es = proportion_effectsize(p2, p1)          # Cohen's h
n = NormalIndPower().solve_power(es, alpha=0.05, power=0.80,
                                 ratio=1, alternative="two-sided")
print(math.ceil(n))                         # 31218 per group

The answer is about 31,218 per group, so about 62,436 users in total. A popular A/B planning skill lists roughly 19,000 per variant for a 5% baseline at a 20% MDE; the correct figure for 5% at a 20% relative MDE is about 8,100, so that table is more than twice too high, which would waste weeks of traffic. With 5,000 eligible users a day at full exposure, the run time is 62,436 / 5,000, about 13 days, which the two-week business-cycle floor rounds to 14 days. The output is: 31,218 per group, run for 14 days, powered to detect a lift from 5% to 5.5% at 80% power and 95% confidence, with the assumptions stated so no one later mistakes the floor for the earliest honest stop.

Templates you can use verbatim

# Proportions: sample size per group, then validate the power
import math
from statsmodels.stats.proportion import proportion_effectsize
from statsmodels.stats.power import NormalIndPower
def n_proportion(p1, mde_rel, alpha=0.05, power=0.80, k_variants=1):
    p2 = p1 * (1 + mde_rel)                              # relative MDE
    alpha_adj = alpha / max(1, k_variants)              # Bonferroni for >1 variant
    es = proportion_effectsize(p2, p1)
    an = NormalIndPower()
    n = an.solve_power(es, alpha=alpha_adj, power=power, ratio=1,
                       alternative="two-sided")
    check = an.power(es, nobs1=math.ceil(n), alpha=alpha_adj,
                     ratio=1, alternative="two-sided")  # should ~= power
    return {"n_per_group": math.ceil(n), "achieved_power": round(check, 3)}
# Means: per group from baseline sd and an absolute delta
import math
from statsmodels.stats.power import TTestIndPower
def n_means(sigma, delta, alpha=0.05, power=0.80):
    d = delta / sigma                                   # standardised effect
    n = TTestIndPower().solve_power(effect_size=d, alpha=alpha, power=power,
                                    ratio=1, alternative="two-sided")
    return math.ceil(n)
Run-time and feasibility check
total = n_per_group * number_of_groups
days  = total / (daily_eligible * share_exposed)
floor = max(days, 7)            # one business cycle, prefer 14
if days > 56:  change the design (bigger MDE, fewer variants, higher-signal metric)
report: n_per_group, total, days (>= floor), alpha, power, MDE basis, assumptions

Failure modes and anti-patterns

  1. Absolute versus relative MDE mix-up. A 10% lift on a 5% baseline is 0.5 points, not 10 points; getting this wrong moves the sample size by orders of magnitude. Spot it by stating the baseline and target as explicit values. Fix: confirm the basis before computing.
  2. Trusting a calculator or table without checking. Many published tables are two to ten times off. Spot it by recomputing the power at the suggested n, or comparing to the reference table here. Fix: use the validator; investigate any gap over about 10%.
  3. Dropping the power term. A formula with only the alpha quantile (missing z for beta) understates the sample size and leaves the test underpowered. Spot it when the number looks suspiciously small. Fix: use a power library, which includes both terms.
  4. Ignoring the business-cycle floor. Hitting the sample in three days and stopping misses weekend behaviour. Spot it from a run time under a week. Fix: run at least one full cycle, preferably two, whatever the maths says.
  5. Post-hoc power. Computing power from the observed effect after the test is circular and uninformative. Spot it when "observed power" is quoted to defend a null result. Fix: report the confidence interval instead (see ab-test-analysis), and never compute power after the fact.

Quality bar

  • The baseline, the MDE and its basis (absolute or relative), alpha, power and sidedness are all stated before the number is computed.
  • The sample size is computed with a power library, cross-checked against the rule of thumb, and validated by recomputing the achieved power.
  • Any disagreement over about 10% with another calculator is explained, not averaged away.
  • The run time applies a business-cycle floor of at least one week (prefer two) and flags a test that would need more than about eight weeks.
  • Multiple variants split alpha, and the higher sample size that follows is reported, not hidden.
  • Post-hoc power is never reported; a finished test is read with a confidence interval instead.

Data handling and safety

Sample-size work uses summary numbers (a baseline rate, a standard deviation, a traffic figure), so it rarely touches personal data; if a baseline is estimated from raw records, do not log or send those records, compute the summary in place. The output sizes a test, it does not launch one: deciding to run an experiment, allocate traffic or delay a release is a human call, and this skill produces a plan, not an action. Never fabricate a baseline, a standard deviation or a traffic figure to make a test look feasible; if an input is missing, ask for it or label the result as conditional on an assumption. When the test informs a decision about money, health, legal standing or employment, an underpowered test can do real harm by missing a true effect, so state the power and the smallest effect the test can detect, and let a human weigh whether that is enough.

Appendix: tool-specific notes (verify before relying on these)

  • statsmodels: NormalIndPower().solve_power(effect_size, alpha, power, ratio, alternative) for proportions with proportion_effectsize(p2, p1) giving Cohen's h; TTestIndPower().solve_power(effect_size=d, ...) for means with d = delta / sigma; GofChisquarePower for chi-square designs. solve_power leaves exactly one of effect_size, nobs1, alpha or power as None and solves for it, so you can also solve for the detectable effect given a fixed sample. Recompute power(...) at the rounded n to validate.
  • Evan Miller's calculator and rule of thumb: n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, a quick sanity check; his online tool is a reputable second source. Verify its MDE basis matches yours.
  • Optimizely and VWO: their sequential Stats Engine does not require a fixed sample size in advance, but a planning estimate still helps; their calculators default to a relative MDE and a baseline, so confirm the basis when comparing. Treat their duration estimates as specific to their sequential method.
  • R: power.prop.test(p1, p2, power, sig.level) and power.t.test(delta, sd, power, sig.level) in base R, and the pwr package (pwr.2p.test, pwr.t.test) using Cohen's effect sizes. R's functions take the effect directly, so state p1 and p2 in their own units.
  • **G*Power:** a trusted desktop tool for cross-checking; match the test family, the tails and the effect-size input exactly, or its answer will differ from the library's.

Sources

  • statsmodels documentation, statsmodels.stats.power (NormalIndPower, TTestIndPower, solve_power, power) and proportion_effectsize: the solve-for-one-parameter design, the effect-size inputs, and recomputing power to validate. Verified 7 November 2026.
  • Evan Miller, "How Not To Run an A/B Test" and "Sample Size Calculator" (2010): the rule of thumb n is about 16 * sigma^2 / delta^2 per group for 80% power and 95% confidence, and that committing to a sample size in advance is what keeps the significance level honest. Verified 7 November 2026.
  • Optimizely documentation, "How long to run an experiment" and the sample size calculator: the default relative MDE and baseline inputs, that higher baselines need smaller samples, that high-variance metrics need more data, and the at-least-one-business-cycle rule. Verified 7 November 2026.
  • Kohavi, Tang and Xu, *Trustworthy Online Controlled Experiments* (2020): that effects are usually small (so MDEs must be realistic), that tests should cover full business cycles, and the cost of underpowered experiments. Verified 7 November 2026.
  • Hoenig and Heisey, "The Abuse of Power: The Pervasive Fallacy of Power Calculations for Data Analysis" (The American Statistician, 2001): that observed or post-hoc power is a function of the p-value and should not be used to interpret a completed test. Verified 7 November 2026.
  • Existing skills reviewed and improved on: the mohitagw15856 ab-test-planner and openclaudia ab-test-setup skills both publish sample-size lookup tables that do not match their own stated formulas, off by factors of roughly two to ten; this skill computes the figure from a power library, ships a validator that recomputes the achieved power, and gives a corrected reference table. Verified 7 November 2026.

When to use this skill, and when not to

Use this skill before a test runs, when you need to know how many users each group needs and how long the test must stay live. It fits planning an A/B test, checking whether your traffic can detect the lift you care about, or working out what effect a fixed sample can find.

It is not for reading a finished test (see ab-test-analysis), for the significance test itself (see hypothesis-testing), or for computing power after the test has run, which is not meaningful.

Who it is for

Product managers, growth and experimentation teams, analysts and anyone planning an experiment. No statistics background is needed: the skill asks for the baseline and the effect you care about in plain terms, and returns the number with its assumptions.

What is inside

A six-step method with the correct formulas, not a lookup table: pin the metric and the minimum detectable effect in its own units, set alpha and power, compute the per-group size with a power library, validate it by recomputing the achieved power, then turn it into a run time with a business-cycle floor and a feasibility ceiling. It includes a corrected reference table, a validator script, and the levers to pull when traffic is too low.

Example prompts

“How many users do I need for this A/B test?” “How long should I run it?” “What lift can I detect with 10,000 visitors a day?” “Is my test big enough?” “Run a power analysis for a 5% baseline and a 10% lift.”

Example output

The skill returns the sample size per group, the total, the run time with a business-cycle floor, and the assumptions behind them (baseline, MDE and its basis, alpha, power). It flags when the traffic cannot support the test and names the trade-offs, and it validates the number so a wrong figure does not slip through.

What the agent needs from you

The baseline rate (or the mean and standard deviation for a continuous metric), the minimum detectable effect and whether it is absolute or relative, your significance level and power, the number of variants, and your daily eligible traffic. If the MDE basis or the standard deviation is missing, the skill asks, because guessing it gives a wrong answer.

How to install and use it

In the Claude apps, use the buttons above to download the skill, then upload the SKILL.md in a new chat or add it to a Project. In Claude Code and other Agent Skills tools, copy the sample-size-calculation folder into ~/.claude/skills/, or .agents/skills/ for Codex. The skill loads itself when your request matches its triggers, so you do not need to call it by name.

How to calculate sample size step by step

State the baseline and the target value in the metric’s own units, and say whether the MDE is absolute or relative. Set alpha (0.05 two-sided) and power (0.80, or 0.90 for high stakes), and split alpha across variants if there is more than one. Compute the per-group size with a power library, cross-check it against the rule of thumb, and validate by recomputing the achieved power. Turn the total into days of traffic, apply a floor of at least one business cycle, and if the test would need more than about eight weeks, change the design instead of running it underpowered.

Worked example

For a pricing page at 5% baseline conversion, wanting a 10% relative lift to 5.5% at 80% power and 95% confidence, the correct size is about 31,218 per group, roughly 62,000 users in total. A popular planning skill would suggest a figure more than twice too large for a similar case, wasting weeks of traffic. With 5,000 eligible users a day, the run time is about 13 days, which the two-week business-cycle floor rounds to 14.

Situations this skill handles

SituationWhat the skill does
Baseline and a relative liftConverts the MDE to the metric’s units and computes the per-group size
A calculator gives an odd numberRecomputes the power to validate and flags gaps over 10%
More than two variantsSplits alpha across comparisons and reports the higher size
Continuous metricUses the mean and standard deviation, not a proportion formula
Traffic is too lowNames the levers: bigger MDE, fewer variants, a higher-signal metric
A finished testRefuses post-hoc power and points to ab-test-analysis

What makes this skill different

Published A/B planning skills ship sample-size tables that do not match their own formulas, off by two to ten times, usually from an absolute-versus-relative mix-up or a dropped power term. This skill computes the figure from a power library, ships a validator that recomputes the achieved power, gives a corrected reference table, applies a business-cycle floor and a feasibility ceiling, and refuses post-hoc power, with every rule sourced.

Common mistakes

The usual errors are confusing an absolute with a relative MDE, trusting a calculator or table without checking, dropping the power term, ignoring the business-cycle floor, and computing power after the test. The skill names each one, shows how to spot it, and gives the fix.

Pair it with hypothesis-testing for the test choice and the maths, and ab-test-analysis to read the test once it has run to this size. For the metric definitions behind a baseline, see metric-selection.

Frequently asked questions

It depends on your baseline, the smallest lift worth detecting, your significance level and your power. As a guide, detecting a 10% relative lift on a 5% baseline at 80% power needs about 31,000 per group. The skill computes the exact figure for your numbers and validates it.

The MDE is the smallest change you want to be able to detect. Whether it is absolute (5% to 15%) or relative (5% to 5.5%) changes the sample size enormously, so the skill always confirms the basis first. Mixing them up is the most common reason a sample-size figure is wrong.

You can, but many calculators and published tables are two to ten times off, often from the absolute-versus-relative mix-up. The skill computes the number from a power library and then recomputes the power at that size to check it, so a wrong figure is caught before you plan around it.

Divide the total sample by your daily eligible traffic, then run for at least one full business cycle, preferably two, even if the sample is reached sooner, so weekday and weekend behaviour are both captured. If the test would need more than about eight weeks, the skill suggests changing the design.

The levers, in order: accept a larger detectable effect, reduce the number of variants, pick a higher-signal metric closer to the change, or use a qualitative method. The skill reports the trade-off rather than letting you run a test too small to conclude anything.

No. Observed or post-hoc power is a function of the p-value and tells you nothing new. If a finished test was flat, read its confidence interval to see what effects it could rule out. See ab-test-analysis.

Changelog

1.0.0, 7 November 2026: first release. Use, adapt and share under CC BY 4.0 with credit to Afeez Adebayo.