ABWex / Tools / False discovery rate calculator

False discovery rate calculator

By Michael Lip. Updated 2026-08-24.

Paste the p values from one experiment. You'll get Benjamini Hochberg, Benjamini Yekutieli, Holm and Bonferroni side by side, with a survives or does not survive verdict for every metric at the alpha you set. It runs in your browser and nothing is uploaded.

Adjust your p values

This tool corrects p values you supply. It doesn't run the underlying test, so the test itself, its tail count and its alpha stay yours to state alongside any result. The drawn example is two sided. Adjusted values are cross checked against statsmodels and the tolerance is recorded below.

How the four corrections work

All four take the same input, your list of raw p values, and hand back adjusted values you compare against alpha. What differs is the quantity each one holds down.

Bonferroni

One multiplication, no ordering. In R's p.adjust it's the method where the p-values are multiplied by the number of comparisons, and Bonferroni, Holm, Hochberg and Hommel are all designed to give strong control of the family-wise error rate. From the other side, a Laryngoscope methods review puts it as generating a stricter significance cutoff by dividing the original significance level by the number of comparisons. statsmodels calls its bonferroni method a one-step correction, which is what it is.

Holm

Holm sorts your p values and walks up the list, so the smallest p faces the full penalty and later ranks face less. statsmodels describes its holm method as a step-down method using Bonferroni adjustments. R puts the practical conclusion this way, that there seems no reason to use the unmodified Bonferroni correction because it is dominated by Holm's method, which is also valid under arbitrary assumptions. The simulation further down agrees on power, in the one cell it covers.

Benjamini Hochberg

BH controls something different. The false discovery rate is the expected proportion of false discoveries amongst the rejected hypotheses, and that's the quantity the BH and BY methods in R's p.adjust control.

That is a weaker promise than holding the whole family, so it buys you detection. R calls it a less stringent condition than the family-wise error rate. SciPy puts the same trade in its own words, that false discovery control procedures tend to offer higher power than familywise error rate control procedures such as the Bonferroni correction.

Benjamini Yekutieli

BY is BH with a penalty for not knowing how your metrics depend on each other. It replaces the target level with that level divided by the sum of one over i across the m tests, and it controls the FDR under the most general form of dependence structure. R notes it's more conservative than BH. Reach for it when you can't argue your metrics are positively related, which is the case the assumptions section below covers.

In statsmodels the string fdr_bh selects the Benjamini/Hochberg (non-negative) procedure and fdr_by selects Benjamini/Yekutieli. The step up table in the calculator shows the mechanism instead of hiding it. Rank the p values smallest first, compare each against alpha times its rank over the number of tests, find the largest rank still under its line, and keep everything at or below that rank.

What tracking several metrics actually costs you

Track ten independent metrics with no real effect on any of them and you'll still crown a false winner 40.2% of the time. Not the 5% your alpha implies. At twenty metrics it's 64.1%.

Other calculators adjust your p values and stop. None of them tell you what watching a handful of metrics does to the odds of shipping a false winner, or what the correction costs you in detection. So I simulated it instead of quoting anyone.

The study is 36 parameter cells at 200,000 simulated experiments each, alpha 0.05, seed 20260728. It sweeps the metric count over 3, 5, 10 and 20, and the correlation between metrics over zero, 0.3 and 0.6.

The third axis is the share of metrics that are true nulls, targeted at 100%, 80% and 50%. That share is a target rather than an exact setting, because a count of true nulls has to be a whole number. At 5 metrics a 50% target is 2 of 5, which is 40%. At 3 metrics the 80% and 50% targets both round to 2 of 3, so they describe the same experiment and the picker offers it once. The cell picker below reports the count each cell actually ran, which is why it lists 33 of the 36 cells.

40.2%
false winner rate at 10 true nulls, no correction
64.1%
same, at 20 metrics
35.5%
at 20 metrics once correlation reaches 0.6
66.6%
BH detection at 20 metrics, half real, against Bonferroni 41.3%

What those four numbers mean

Ten metrics, every one a true null, nothing corrected, and at least one comes back a winner four times in ten. That's the headline. At twenty metrics it's closer to two in three.

Correlated metrics soften the problem without fixing it. Hold the count at 20 true nulls and move from independent metrics to a correlation of 0.6, and the false winner rate drops from 64.1% to 35.5%. Better. Still nothing like 5%.

Benjamini Hochberg keeps far more of your detection than Bonferroni once the metric count grows. At 20 metrics with half carrying a real effect, BH found 66.6% of the true effects against Bonferroni's 41.3%, and its realised false discovery proportion averaged 2.5%. Holm found more than plain Bonferroni in that same cell too, 44% against 41.3%, with both holding the false winner rate under the study alpha.

Pick a cell and look at it

The known answer check

A simulation you can't check is a story. When every metric is a true null and nothing is corrected, the family-wise error rate has a closed form, 1 − (1 − α)m, where m is the number of simultaneous comparisons. That is the same quantity the Laryngoscope review of multiple hypothesis testing describes.

Measured against that formula, at 3 metrics the study got 14.3% where the formula gives 14.3%. At 5 metrics, 22.5% against 22.6%. At 10 metrics, 40.2% against 40.1%. At 20 metrics, 64.1% against 64.2%. The largest gap across the four rows is 0.14 of a percentage point, at 5 metrics. That agreement is the reason to trust the cells where no closed form exists.

What has to be true for these numbers to hold

SciPy states the guarantee carefully. When p-values correspond to independent tests, or to tests with positive regression dependencies, rejecting the hypotheses whose BH adjusted p-values fall below q controls the false discovery rate at a level no greater than q times the number of true nulls over the number tested.

Metrics that move together are usually fine, and that's a result rather than a hope. Benjamini and Yekutieli proved that BH also controls the false discovery rate when the test statistics have positive regression dependency on each of the test statistics corresponding to the true null hypotheses. Their paper says the condition covers multivariate normal test statistics with positive correlation matrix, multivariate t, and comparisons of many treatments with a single control. Revenue, orders and add to cart on the same visitors sit in that family.

Negative correlation is the gap here, and naming it beats inventing an estimate. The correlation cells in this study are positive only, so a family of strongly negatively correlated metrics is outside what was measured. For all other forms of dependency Benjamini and Yekutieli give a simple conservative modification of the procedure. That's the BY column in the calculator above, so the gap has an answer even though the simulation doesn't cover it.

Two more limits worth naming.

How this calculator was checked

The adjusted values here were compared against statsmodels multipletests across 3,600 reject decisions, spanning families of two up to fifty simultaneous tests. Every reject decision matched. The largest absolute difference in adjusted p values was 2.22e-16, which is floating point noise rather than disagreement.

statsmodels returns a reject array that is true for hypotheses that can be rejected at the given alpha, together with p-values corrected for multiple tests, and both halves were compared. SciPy documents that its own adjusted values are comparable to those produced by the R function p.adjust and by statsmodels multipletests, so the three reference implementations agree on the values this page reproduces.

Where these numbers come from

Built by Michael Lip, who maintains the open source statistics routines behind this site, MIT licensed at github.com/theluckystrike/abwex.com. Those routines include the normal and inverse normal CDF, the Lanczos log gamma, a regularized incomplete beta by continued fraction, and Simpson rule integration for the probability that B beats A.

Nothing here is typed by hand into copy. Adjusted values come from the code in this page, recomputed from whatever you paste. The study figures are read from the dataset committed to that repository.

The run behind them, 36 cells at 200,000 experiments each on seed 20260728, was performed for this page. Both files are published so you can rerun it instead of trusting a table.

Where a closed form exists the simulation is checked against it before publishing, which is the check printed above. The one thing this site doesn't have is a live data feed, and it never claims one. Everything you see is either your own input recomputed in front of you, or a dataset in the repository carrying its seed and its generator.

Common questions

Do I need a correction for only two metrics
The penalty is small, but small isn't zero. Optimizely puts the general shape of it well, that with traditional statistics the risk of generating at least one false positive result increases as you add more metrics and variations to an experiment. Paste both p values into the tool and look at what the correction costs, rather than deciding it in the abstract.
False discovery rate or false positive rate
Different denominators. Optimizely defines the false positive rate as the proportion of false positives out of all negative outcomes, which is a different denominator from the false discovery rate. The second one is scoped to the hypotheses you actually rejected, so it's the one that speaks to a shipping decision.
Is Benjamini Hochberg what the experimentation platforms use
Optimizely's Stats Engine uses a tiered version of the Benjamini-Hochberg procedure for false discovery rate control across multiple metrics and variations. Optimizely also describes false discovery rate control as a statistical procedure for correcting multiplicity caused by running multiple hypothesis tests simultaneously, which is the same job this page does on p values you paste in.
Which column should I read first
If a false winner costs you a release you can roll back, read the Benjamini Hochberg column, since it holds down the share of false discoveries among your winners and keeps more detection. If one false claim leaves the building and can't be walked back, read Holm, which controls the stronger family-wise quantity and still beat plain Bonferroni on detection in the cell measured here. If you can't argue your metrics are positively related, read Benjamini Yekutieli.
Where do the papers live
Benjamini and Hochberg 1995 is titled Controlling the false discovery rate, a practical and powerful approach to multiple testing, DOI 10.1111/j.2517-6161.1995.tb02031.x. Holm 1979 is A Simple Sequentially Rejective Multiple Test Procedure, JSTOR 4615733. Both are listed with journal, volume and pages in the R p.adjust references, Benjamini and Hochberg in Journal of the Royal Statistical Society Series B, 1995, volume 57, pages 289 to 300, and Holm in Scandinavian Journal of Statistics, 1979, volume 6, pages 65 to 70. Benjamini and Yekutieli, The control of the false discovery rate in multiple testing under dependency, ran in The Annals of Statistics volume 29, issue 4, 2001, pages 1165 to 1188, DOI 10.1214/aos/1013699998.

Read this before you act on the output

Related, post hoc power calculator for the number reviewers ask for after a null result, and why the confidence interval answers it better.