On this page

The P-value Is Not a Verdict: An Interactive Consonance Curve

statistics
interactive
Drag an estimate and its interval and watch the entire P-value function, every compatibility interval, and the S-value move together.
Author

Zad Rafi

Published

September 16, 2026

A single P-value reports one number about one hypothesis. The P-value function reports the same test statistic applied to every candidate parameter value at once — and it contains every compatibility interval at every level as horizontal slices. Nothing below is new mathematics. It is the same normal approximation you already use, drawn in full instead of evaluated at one point.

1 Slice the curve at height p=0.05p = 0.05 and read off the x-coordinates: those are the 95% limits. Slice at p=0.01p = 0.01 and you have the 99% limits. The interval was never a separate calculation.

The display is old. Poole called for it in 1987, Sullivan and Foster catalogued its uses in 1990, and it has sat in Modern Epidemiology ever since. What has changed is that it now costs nothing to render, and that we have a better vocabulary for the vertical axis: compatibility rather than confidence, and surprisal rather than significance.

TipDefinitions, once

A P-value function (equivalently, a consonance or compatibility curve) plots, for every candidate parameter value μ\mu, the P-value from testing μ\mu against the data under the full set of analysis assumptions.

An S-value is the Shannon transform s=log2ps = -\log_2 p: the number of consecutive heads from a fair coin that would be exactly as surprising as the observed test statistic, if μ\mu and every other assumption were correct.

A 95% compatibility interval is the set of μ\mu whose P-value exceeds 0.05 — a horizontal slice through the curve, not a separate object.

The explorer

Move the sliders. Everything recomputes in the browser — no server, no round trip.

Plot = Module {Area: class, Arrow: class, BarX: class, BarY: class, Cell: class, Contour: class, Density: class, Dot: class, Frame: class, Geo: class, Hexgrid: class, Image: class, Line: class, Link: class, Mark: class, Raster: class, Rect: class, RuleX: class, RuleY: class, Text: class, …}
  import {consonanceCurve as consonanceCurve, testValue as testValue, seFromRatioCI as seFromRatioCI} from "./ojs/stats.js"
zq = ƒ(L)
est = 1.61
cir = 2.6
mu = 1
level = 0.95
limits = Object {lower: 0.9984796134431281, upper: 2.5960469949521334}
se = 0.24375739874925995
slice = Object {p: 0.050000000000000044, lower: 0.9984796130585426, upper: 2.5960469959520553}
curve = Array(601) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …]
atMu = Object {mu: 1, p: 0.050734109671123656, s: 4.300900160352262}
1.61 (95% compatibility interval 1.00 to 2.60)
Testing μ = 1.00: P = 0.051, S = 4.3 bits
The data are no more surprising against μ = 1.00 than 4.3 consecutive heads from a fair coin.
95.0% slice (at P = 0.050): 1.00 to 2.60
0.00.20.40.60.81.0↑ P-value0.50.7511.52345Rate ratio →95% slice
05101520↑ S-value (bits of information against)0.50.7511.52345Rate ratio →S = 4.3 bits (P = 0.05)

Calibrating bits

The S-value exists because “P = 0.05” carries no intuition and “significant” carries the wrong one. Bits do carry intuition, because everyone has a physical model of coin flipping. Drag μ above and watch the coins.

4.30 bits against μ = 1.00. Less surprising than the conventional 0.05 threshold.

The S-value measures surprise at the whole model, not at μ\mu alone. Every bit is also a bit against the assumed absence of uncontrolled confounding, selection effects, measurement error, and model form. A large S-value says the data are hard to reconcile with the conjunction of μ\mu and everything else you assumed; it does not tell you which conjunct to abandon. In observational work, the “everything else” is usually the weaker link.

A worked example: one data set, four analyses

Brown and colleagues studied serotonergic antidepressant use in pregnancy and autism spectrum disorder in 35,906 Ontario births, of which 2,837 pregnancies (7.9%) were exposed. They reported four hazard ratios from the same cohort under progressively stronger confounding control. This is the example reanalysed at length in, and the working code for that paper lives .

Look at the point estimates before you look at anything else.

brown = Array(4) [Object, Object, Object, Object]
brownStats = Array(4) [Object, Object, Object, Object]
AnalysisConfounding controlHR95% CIInterval ratioP (vs HR = 1)S (bits)
CrudeNone2.161.64 – 2.861.745.7e-824.07
Covariate-adjustedRegression adjustment1.591.17 – 2.171.850.00338.26
HdPS IPT-weightedHigh-dimensional propensity score1.610.997 – 2.592.600.05054.31
Sibling-matchedWithin-family (shared confounders)1.600.69 – 3.745.420.27571.86

Three of the four point estimates are 1.59, 1.60 and 1.61. By the conventional reading, one of them is a finding and two of them are nothing. What actually changed between them is not the estimate — it is the width of the interval, which grows from a ratio of 1.9 to 5.4 across the three adjusted analyses as each trades precision for stronger confounding control. The verdicts flip; the estimate does not move.

The published conclusion was that exposure “was not associated with” autism. That sentence is doing work the arithmetic will not support: the IPT-weighted analysis puts P=0.0505P = 0.0505 against the null, 4.31 bits of surprise, and its interval runs to 2.59.

shown = Array(4) [Object, Object, Object, Object]
brownCurves = Array(2004) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …]
Covariate-adjustedCrudeHdPS IPT-weightedSibling-matched
0.00.10.20.30.40.50.60.70.80.91.0↑ P-value0.50.7511.52345Hazard ratio →

Uncheck the crude analysis and the remaining three curves are near-concentric: same peak, different width. That is the shape of a precision problem, not a disagreement about effect size. Now test a value other than the null:

muBrown = 1.5
AnalysisHRP (vs 1.50)S (bits)Reading
Crude2.160.0106.62Poorly compatible
Covariate-adjusted1.590.7120.49Highly compatible
HdPS IPT-weighted1.610.7710.37Highly compatible
Sibling-matched1.600.8810.18Highly compatible

Set the slider to 1.5 and all four analyses agree: SS = 6.6, 0.5, 0.4 and 0.2 bits. Three of the four find a 50% increase in hazard less surprising than a single coin flip. The analysis that was “not significant” and the analysis that was “significant” are, against this hypothesis, saying nearly the same thing.

Testing HR = 1 is a legitimate question. Reporting only that test, and only its dichotomised outcome, discards the answer to every other question the same data address — including questions the reader may care about more, such as whether an effect large enough to change prescribing can be ruled out. On these data it cannot: the IPT-weighted 95% interval reaches 2.59, and even the 50% interval runs from 1.37 to 1.90.

What more data would do

Precision and parameter value are separate things that a single P-value fuses into one number. Hold the IPT-weighted estimate fixed and vary only the information: the standard error scales as 1/k1/\sqrt{k} when the sample size is multiplied by kk.

kInfo = 1
base = Object {hr: 1.61, se: 0.24354079775495885}
scaled = Object {se: 0.24354079775495885}
scaledCurve = Array(501) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …]
baseCurve = Array(501) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …]
scaledAtNull = Object {mu: 1, p: 0.050528853158511446, s: 4.306748753957083}
At 1.00× the original sample size, with the estimate held at 1.61: 95% interval 1.00 to 2.59, P = 0.0505 against the null, S = 4.3 bits.
0.00.20.40.60.81.0↑ P-value0.50.7511.52345Hazard ratio →

The dashed ghost is the study as published. Push kk to 4 and the null falls well outside the 95% interval without the estimate having moved a hair. Pull kk down to 0.3 and the same estimate becomes compatible with almost everything between 0.7 and 3.9.

This is worth sitting with, because it is the mechanism behind most “failure to replicate” reporting. A study that reports P=0.04P = 0.04 and a study that reports P=0.12P = 0.12 can have identical point estimates and differ only in how many people they enrolled. Neither number is a property of the effect.

ImportantThe one thing this widget cannot show

Scaling the standard error models random error only. Multiplying the sample size by 16 does nothing to confounding, selection, or measurement error — those biases do not shrink with n\sqrt{n}, and past some sample size they dominate entirely. A very narrow curve centred in the wrong place is the most confident way to be wrong. If you want that quantified rather than assumed away, the tool is bias analysis, not more subjects.

Do two estimates conflict?

“Study A was significant, study B was not, so they disagree” is a comparison of two verdicts, not of two estimates. The comparison that answers the question is a curve in its own right: under independence, the log ratio-of-ratios has standard error seA2+seB2\sqrt{se_A^2 + se_B^2}, and the null of no difference sits at a ratio of 1.

Study A is the explorer at the top of this page. Set study B here.

estB = 1.05
cirB = 1.6
limitsB = Object {lower: 0.8300978857941996, upper: 1.3281566172707193}
seB = 0.11990108822230006
diff = Object {ratio: 1.5333333333333334, se: 0.2716504010707466}
diffDomain = Object {from: 0.25, to: 4.6000000000000005}
diffCurve = Array(501) [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …]
diffAtNull = Object {mu: 1, p: 0.11560129228171975, s: 3.1127705693843435}
Study A: 1.61 (1.00–2.60), P vs 1 = 0.051
Study B: 1.05 (0.83–1.33), P vs 1 = 0.684
Ratio of ratios A ÷ B = 1.53 (95% CI 0.90–2.61), P for no difference = 0.116, S = 3.1 bits
0.00.20.40.60.81.0↑ P-value for the difference0.30.40.50.61234Ratio of ratios (A ÷ B) →

With the defaults — A at 1.61 (P=0.051P = 0.051) and B at 1.05 (P=0.684P = 0.684) — the two studies land on opposite sides of the conventional threshold. Their ratio of ratios is 1.53, 95% interval 0.90 to 2.61, and the difference carries 3.1 bits of information: fewer than the 4.3 bits the 0.05 convention itself demands, and fewer than four coin flips. Two verdicts that disagree, one comparison that does not.

WarningThis does not apply to the four Brown analyses

The overlay in the previous section shows four analyses of the same subjects. Their estimates are strongly correlated, so seA2+seB2\sqrt{se_A^2 + se_B^2} badly overstates the standard error of their difference and the resulting P-value is not interpretable. Use this widget for genuinely independent studies. For nested analyses of one data set, the honest summary is the overlay itself: same peak, different width.

A P-value and an S-value are the same quantity on different scales, so a dual axis is technically defensible. It is still a bad idea: readers reliably misread which curve belongs to which axis, and the visual slope of the P-value curve near the tails is uninformative precisely where the S-value is most informative. Two stacked panels sharing an x-axis cost one extra inch of page and remove the ambiguity.

  • No shading of “significant” regions. The point of the curve is that there is no cliff at 0.05.
  • No default null at 1. The μ slider starts at 1 because that is the conventional test value, not because it is privileged.
  • No P-value below about 1e-300. Double precision runs out. The implementation stays accurate to roughly z = 37, which is far past the point where the normal approximation itself is the binding constraint.
  • No normality diagnostics. Every curve here assumes the log estimate is approximately normal with the reported standard error. That is the same assumption the published interval already made; the curve does not add it, it only makes it visible across the whole range.

Interactive table

The same idea applied to tabular results — searchable and sortable by clicking column headers, which is most of what makes a long results table usable. These are the Brown analyses again, with each row carrying its own P-value against a hypothesis you choose.

muTable = 1
tableRows = Array(4) [Object, Object, Object, Object]
4 results
tableSearch = Array(4) [Object, Object, Object, Object]
AnalysisHazard ratio95% CISE (log scale)PS (bits)
Crude2.161.64 – 2.860.1425.7e-824.07
Covariate-adjusted1.591.17 – 2.170.1580.0038.26
HdPS IPT-weighted1.610.997 – 2.590.2440.0514.31
Sibling-matched1.60.69 – 3.740.4310.2761.86

How to report this

Nothing above requires a new statistic, a new threshold, or a new software stack. It requires four sentences you can paste into a results section:

  1. Report the estimate and interval without the word “significant” — “HR 1.61, 95% compatibility interval 0.997 to 2.59”.
  2. Report the P-value as a number, not as an inequality against 0.05, and say what hypothesis it tests.
  3. Report at least one P-value for a non-null hypothesis that matters clinically or practically. If the data cannot distinguish the null from a 60% increase, that is the finding.
  4. Say that the interval and P-value are conditional on the entire model, not just on the parameter.

If a reviewer asks for the significance verdict back, the curve is the reply: it contains their verdict as one horizontal slice, plus every slice they did not ask for.

Reader infrastructure that is already on

Three things people associate with Gwern’s pages are Quarto defaults and need no code at all:

  • Citation popups. Hover any @citekey reference.
  • Footnote popups. Hover the marker on above.
  • Cross-reference popups. Hover any @fig- or @tbl- reference.

2 The convention that 0.05 marks a boundary is worth pricing in bits: it is 4.32 bits of information against the tested hypothesis, or roughly the surprise of four consecutive heads. Few people would abandon a belief on four coin flips.

All three are controlled by citations-hover, footnotes-hover and crossrefs-hover, which default to true. The margin placement of footnotes here comes from reference-location: margin in this document’s front matter.

References

1. Poole C. (1987). “Beyond the confidence interval.” American Journal of Public Health. 77:195–199. doi: .
Abstract

Beyond the confidence interval. C PooleCopyRight https://doi.org/10.2105/AJPH.77.2.195 Published Online: October 07, 2011

2. Sullivan KM, Foster DA. (1990). “Use of the confidence interval function.” Epidemiology. 1:39–42. doi: .
Abstract

Graphics displaying all confidence intervals around a point estimate have been referred to as P-value functions and consonance intervals. We recommend use of the term confidence interval function (CI function) rather than P-value function. The CI function is useful because it simultaneously depicts point estimation, variability, and the relation of these two factors to the null value. The usefulness of the CI function in demonstrating the concepts of effect modification and confounding, in meta-analysis, and in the comparison of various confidence interval procedures is evaluated. Software packages that produce CI functions are described.

3. Rafi Z, Greenland S. (2020). “Semantic and cognitive tools to aid statistical science: Replace confidence and significance by compatibility and surprise.” BMC Medical Research Methodology. 20:244. doi: .
Abstract

BACKGROUND: Researchers often misinterpret and misrepresent statistical outputs. This abuse has led to a large literature on modification or replacement of testing thresholds and P-values with confidence intervals, Bayes factors, and other devices. Because the core problems appear cognitive rather than statistical, we review some simple methods to aid researchers in interpreting statistical outputs. These methods emphasize logical and information concepts over probability, and thus may be more robust to common misinterpretations than are traditional descriptions. METHODS: (p), to provide a measure of the information supplied by the testing procedure, and to help calibrate intuitions against simple physical experiments like coin tossing. We also use tables or graphs of test statistics for alternative hypotheses, and interval estimates for different percentile levels, to thwart fallacies arising from arbitrary dichotomies. Finally, we reinterpret P-values and interval estimates in unconditional terms, which describe compatibility of data with the entire set of analysis assumptions. We illustrate these methods with a reanalysis of data from an existing record-based cohort study …

4. Brown HK, Ray JG, Wilton AS, Lunsky Y, Gomes T, Vigod SN. (2017). “Association between serotonergic antidepressant use during pregnancy and autism spectrum disorder in children.” JAMA. 317:1544–1552. doi: .
Abstract

IMPORTANCE: Previous observations of a higher risk of child autism spectrum disorder with serotonergic antidepressant exposure during pregnancy may have been confounded. OBJECTIVE: To evaluate the association between serotonergic antidepressant exposure during pregnancy and child autism spectrum disorder. DESIGN, SETTING, AND PARTICIPANTS: Retrospective cohort study. Health administrative data sets were used to study children born to mothers who were receiving public prescription drug coverage during pregnancy in Ontario, Canada, from 2002-2010, reflecting 4.2% of births. Children were followed up until March 31, 2014. EXPOSURES: Serotonergic antidepressant exposure was defined as 2 or more consecutive maternal prescriptions for a selective serotonin or serotonin-norepinephrine reuptake inhibitor between conception and delivery. MAIN OUTCOMES AND MEASURES: Child autism spectrum disorder identified after the age of 2 years …

Back to top

Comments

Webmentions

Replies, likes, and mentions from around the web, tracked via .