2 * pt(abs(1.46), df = 58, lower.tail = FALSE)[1] 0.1496857
What does this result mean?
t(58) = 1.46, p = .03
For many of us, attention goes straight to the p-value. It is below .05, so the result is “significant”, and that is often where reading stops. Researchers, reviewers, and editors pay much more attention to p-values than to test statistics and degrees of freedom, not least because articles are more likely to be published when their results are statistically significant (Franco et al., 2014; Sterling, 1959). The t and its degrees of freedom tend to be read past.
But the t and the degrees of freedom are not decoration. Together, they determine the p-value: given t = 1.46 and df = 58, there is only one two-sided p-value that can follow. The p-value is therefore repeated information, because it can be recalculated from other numbers in the same sentence. And because few readers ever do this, the test statistic and degrees of freedom are overlooked information. These are the two ingredients of Brown’s Law:
Most forensic meta-science checks rely on information that is repeated or overlooked.
Brown’s Law (2026)
Recalculating the p-value from the test statistic and degrees of freedom gives:
t(58) = 1.46, p = .03 ➔ p = .15
The reported p-value does not match the recalculated one, and not by a little: the result changes from significant to non-significant.
As with all forensic meta-science checks, it is not possible to know from a single inconsistency what process caused it. It could be a typo in any of the three numbers, a value copied from the wrong line of the output, a one-sided test that was not described as one-sided, a correction to the p-value that was applied but not reported, or someone replacing an undesired non-significant p-value with a significant one. What an inconsistency does tell us is that the three numbers cannot all be correct for the test that the article appears to describe.
Under the null hypothesis, the t statistic of a t-test follows a t distribution with df degrees of freedom. The two-sided p-value is the probability of a t at least as far from zero as the observed one, in either direction:
\[ p = 2 \times P(T_{df} \geq |t|) \]
where \(T_{df}\) is a random variable that follows the t distribution with df degrees of freedom. This probability is the area under the two tails of the distribution, beyond −|t| and beyond |t|. There is no simple closed-form expression for it, but it is easily calculated with software. In R, pt() gives the area to the left of a value, so the area in the upper tail is pt(abs(t), df, lower.tail = FALSE), and the two-sided p-value is twice that:
2 * pt(abs(1.46), df = 58, lower.tail = FALSE)[1] 0.1496857
A one-sided p-value is the area in one tail only, which for a result in the predicted direction is half the two-sided p-value. The p-values of other tests are calculated in the same way, from their own distributions: an F statistic with df1 and df2 degrees of freedom from the F distribution (pf()), a χ² statistic from the χ² distribution (pchisq()), and a z statistic from the standard normal distribution (pnorm()). A correlation r with df = N − 2 is first converted to a t statistic, \(t = r \sqrt{df / (1 - r^2)}\), and then treated as a t.
The {statcheck} R package (Nuijten et al., 2016; Nuijten & Epskamp, 2025) and the web app at statcheck.io automate this. statcheck searches the text of an article for results reported in APA style, such as “t(58) = 1.46, p = .03” or “χ²(1, N = 226) = 6.90, p < .01”. It currently recognises t, F, r, χ², z, and Q statistics. For each result it finds, it recalculates the p-value from the test statistic and degrees of freedom, and compares it with the reported p-value. Each result is then classified as consistent, as inconsistent (which statcheck calls an “error”), or as inconsistent-and-decision-changing (which statcheck calls a “decision error”): an inconsistency where the reported and recalculated p-values fall on opposite sides of α = .05, so that the statistical conclusion changes. I employ consistent/inconsistent throughout this book for, uh, consistency.
The box below runs the {statcheck} R package itself, inside your browser, using webR, a version of R that runs in web pages. Paste results copied from an article, one per line, and click the button. The text you paste is not sent anywhere: R runs on your own computer. The first run takes several seconds, because R and statcheck have to be downloaded, and later runs are almost instant. Lines that statcheck does not recognise as an APA-style result are listed as not recognised, which is a quick way to see the limits of its extraction for yourself. Note that the version of statcheck that is available for webR is not the most recent version, for reasons internal to webR. More recent versions have a robust_rounding argument that makes results more concervative.
Several of the default examples are worth a closer look. F(1, 7) = 12.19, p < .001 is one of the results that Schmidt (2017) reported was flagged in his own article. It is inconsistent, because its p-value is .010, but it does not change the conclusion. r(40) = −.30, p = .03 is grossly inconsistent, whereas r(40) = .3, p = .03, one of the examples in the plot in Section 10.1.1.3, is consistent: the second decimal narrows the range of possible p-values enough to exclude .03. And the last example, which has an MSE between the test statistic and the p-value, is not recognised at all.
Nuijten et al. (2016) used statcheck to check every article published in eight major psychology journals between 1985 and 2013: 30,717 articles in total. statcheck found APA-style results in 16,695 of them (54.4%), and these articles reported 258,105 p-values.
49.6%
of articles (8,273 of 16,695) contained at least one inconsistent p-value.
12.9%
of articles (2,150) contained at least one grossly inconsistent p-value.
9.7%
of all p-values (24,961) were inconsistent.
1.4%
of all p-values (3,581) were grossly inconsistent.
That is, around half of psychology articles that report significance tests contain at least one p-value that does not match its test statistic, and around one in eight contain one where the mismatch changes whether the result is significant.
The inconsistencies were also not symmetric. Of all p-values reported as significant, 1.56% were grossly inconsistent, compared with 0.97% of those reported as non-significant.
1.6×
as likely to be grossly inconsistent when a p-value was reported as significant as when it was reported as non-significant.
This is what we would expect if errors that produce significant results are more likely to be made, less likely to be caught, or more likely to be published. Nuijten et al. (2016) discuss all three possibilities, and their data cannot distinguish between them.
These figures are estimates, and depend on what statcheck can read. statcheck only reads results reported in full APA style in the text. When Nuijten et al. (2016) compared statcheck with a manual check of 49 articles, statcheck found 67.5% of the results that had been extracted by hand. Most of the results it missed were in tables, or had an effect size or other statistic between the test statistic and the p-value (e.g., “F(2, 70) = 4.48, MSE = 6.61, p < .02”). How common inconsistencies are among the results that statcheck does not read is unknown.
A reported test statistic is a rounded number. When an article reports t(28) = 2.0, the t that was calculated from the data could have been anything from 1.95 to 2.05, all of which round to 2.0. These values of t give two-sided p-values from .0613 down to .0498. A reported p < .05 is therefore consistent with t(28) = 2.0, even though the p-value recalculated from exactly 2.0, .055, is not below .05. If rounding were ignored, perfectly correct results would be flagged as errors whenever the test statistic was reported with few decimals.
It is not widely understood that statcheck accounts for this. For each result, it does not calculate a single p-value, but the range of p-values that could have produced the reported result after rounding. It takes the test statistic as reported, adds and subtracts half a unit of its last reported decimal (± 0.05 for t = 2.0, ± 0.005 for t = 1.46), and calculates the p-value at each end of this range. statcheck returns these bounds as computed_p_lower_bound and computed_p_upper_bound. Then, if the reported p-value is exact (e.g., p = .03), statcheck rounds the two bounds to the same number of decimals as the reported p-value and checks whether the reported value lies between them. If the reported p-value is an inequality (e.g., p < .05), it checks whether any p-value in the range satisfies it. Only if the reported p-value is incompatible with the whole range is the result flagged.
The plot below shows how this works. Type a result in APA style into the box, or choose one of the examples. The upper panel shows the p-value as a function of the test statistic, on a logarithmic scale so that very small p-values can be seen. The blue dot is the recalculated p-value, and the orange line is the reported one; for a reported inequality, the shaded region shows the p-values it allows. The orange dot shows the test statistic that the reported p-value would require. The lower panel zooms in on the reported test statistic. Its vertical blue band shows the values of the test statistic that round to the reported value, and its horizontal blue band shows the range of p-values that these produce. The first button switches between two-sided and one-sided tests, and the second turns the accommodation of rounding on and off, so that you can see which results would be flagged without it. The classification follows statcheck’s rules, with α = .05.
Several things are worth trying:
statcheck only accommodates the rounding of the test statistic. The degrees of freedom are taken as reported. This rarely matters, because degrees of freedom are usually whole numbers that need no rounding. But some tests have fractional degrees of freedom, such as Welch’s t-test and corrected repeated-measures ANOVAs. If an article reports t(28.53) as t(29), the recalculated p-value will be slightly off, and a result near the boundary of the check can be flagged because of it. Recent versions of statcheck also offer robust_rounding = TRUE, which widens the range to a whole unit of the last reported decimal either side of the test statistic, for when the rounding of the reported values is uncertain.
An inconsistency means that the reported p-value cannot be recalculated from the reported test statistic and degrees of freedom under the assumptions of the check. When those assumptions do not hold, correctly reported results can be flagged (false positives), and incorrect ones can pass (false negatives). Schmidt (2017) described several of these, using statcheck’s reports on two of his own articles as examples.
The most important is that statcheck cannot know about corrections to the p-value. Many analyses correctly adjust the p-value after it has been calculated from the test statistic: corrections for multiple comparisons (e.g., Bonferroni or Holm), post-hoc tests (e.g., Tukey or Scheffé), and corrections for violations of sphericity in repeated-measures ANOVA (Greenhouse-Geisser or Huynh-Feldt), which multiply the degrees of freedom by a correction factor ε. In each case, the reported p-value is larger than the one implied by the reported test statistic and degrees of freedom, and statcheck flags it. One of Schmidt’s articles reported all F tests with Huynh-Feldt corrected p-values and the uncorrected degrees of freedom. statcheck detected 86 of its 98 tests and flagged 18 of them. On checking, 4 of the 18 were real errors, and the other 14 were correctly corrected p-values.
Nuijten et al. (2016) acknowledged this, but argued that it would rarely matter, because only 0.3% of the articles they checked contained the string “Bonferroni” and only 0.03% contained “Huynh-Feldt”. Schmidt found that “Bonferroni” appeared in 7.6% of the roughly 800 articles in his own collection and “post-hoc” in 13.7%, and pointed out that the 49 articles in Nuijten et al.’s own validity check included two with Huynh-Feldt corrections, which would be very unlikely if the true rate were 0.03%. How often corrections cause false positives therefore depends heavily on the field and the type of design.
The same logic produces false negatives. A result that needed a correction but was reported without one is internally consistent, and passes. So does a p-value that was calculated from the wrong test, from data with errors in it, or from a fabricated test statistic that was chosen to match it. statcheck checks whether three reported numbers are consistent with one another. It does not check whether the analysis was appropriate, or whether the numbers are correct. A result that passes has not been shown to be correct.
Other sources of false positives include:
OneTailedTxt = FALSE). Articles also do not always say that a test was one-sided.pZeroError = TRUE). This is correct, but it is a reporting convention error rather than a miscalculation, and some manual checks do not count it. In Nuijten et al.’s validity check, 11 of the 56 inconsistencies that statcheck found were reports of p = .000.The lesson is that a statcheck flag is a reason to read the article more closely, not a finding in itself. Before treating an inconsistency as an error, check the original text to confirm that the numbers were extracted correctly, read the methods and the table notes for corrections and one-sided tests, and consider whether the reported p-value could be a correctly adjusted one.
Many of these problems, and many disagreements between tools that use statcheck, are easier to diagnose once the method, its implementation in the {statcheck} package, and the tools that use it are kept apart. This is the subject of Chapter 23.
recalc, importance of rounding, precision
Many articles, particularly experiments and RCTs, report each group’s mean, SD, and sample size. Some explicitly report a Standardized Mean Difference (aka Cohen’s d). Like the recalculation of p-values, this provides information that is repeated and often overlooked. Either the SMD can be recalculated from the summary statistics (N/M/SD) and checked for consistency or, if not reported at all, it can be checked for plausibility (Chapter 8).
Calculation of SMD effect sizes can be done the same way as meta-analysts do, e.g., using R packages that implement the formula for SMD. For example, the escalc() function from the {metafor} R package (Viechtbauer, 2010) calculates many different forms of effect size and their sampling variances from summary statistics. Here we are only considering SMD.
Imagine an article reports the following table of results, either as a table or in text. Bear in mind that sometimes the individual summary statistics have to be assembled from different sections of the article.
| Group | M | SD | n |
|---|---|---|---|
| Intervention | 11.2 | 4.9 | 64 |
| Control | 25.1 | 4.1 | 64 |
Using a SMD calculator like the one below, we can calculate the SMD for this study. The calculator starts with this study. The Four studies button loads four hypothetical studies instead, to show that it can calculate the effect sizes of many studies at once, as a meta-analyst would, and This study switches back. As you can see, something might be off in the example: a SMD greater than 3, in a study with 64 participants per group, is far outside the range that sampling error can produce unless the true effect is itself enormous (Section 8.2).
The previous example treats the means, SDs, and any reported SMD estimate as exact values, when in reality they are usually rounded to a few decimal places.
Unlike statcheck (Section 10.1.1.3), most effect size calculators for meta-analyses don’t taking this rounding into account, because the imprecision they introduce typically isn’t big enough to affect meta-analyses.
But for forensic purposes, it often does matter. M = 11.2 could have been anything from 11.15 to 11.25, and SD = 4.9 anything from 4.85 to 4.95. Across all the values that round to the four reported statistics in the example, the (re)calculated SMD (Hedges’ g, −3.06 from the values as reported) could then range from −3.00 to −3.12. A reported SMD of −3.10 would therefore be consistent with the summary statistics, even though the calculator above gives −3.06.
In addition to this, whereas a meta-analyst only wants to calculate one SMD effect size using a specific set of analytic choices, a forensic meta-scientist would instead want to consider whether the reported estimate can be recalculated under many different sets of analytic choices, given that most articles will not report which exact choices were employed. For example, whether Hedges’ correction for small sample sizes was applied, and if so, whether its exact or approximate form was used; which SD the mean difference was divided by (the pooled SD with n1 + n2 − 2 degrees of freedom, the pooled SD with n1 + n2, or the square root of the average of the two variances); which group’s mean was subtracted from which, which changes the sign; and whether values reported as SDs were in fact standard errors (Section 6.2). The confidence interval adds further choices: a Wald interval based on the t or the normal distribution, or with Welch’s degrees of freedom, or an interval based on the noncentral t distribution, and one of several formulas for the standard error of d.
The calculator below does this. It runs the recalc_independent_t() function from the {recalc} R package in your browser, using webR in the same way as the statcheck app (Section 10.1.1.1), and loads {recalc} in the same way as the subgroup calculator (Section 10.3.1.1). Enter each group’s mean, SD, and sample size, and whichever of the p-value of the t-test, the SMD, and its 95% confidence interval the article reports. For every combination of the rounding of the means and SDs and the analytic choices above, it recalculates all three, and says whether each reported value could have been produced by at least one combination. For the confidence interval, a single combination has to produce both of its bounds. As in the subgroup calculator, the number of decimal places of each kind of value is taken from the values as you typed them, so type 4.70 rather than 4.7 if the article reported two decimals. The two examples are the study above, whose reported values are all consistent, and the hypothetical study in the {recalc} documentation, whose p-value and SMD are consistent but whose confidence interval is not.
Many results take the form of a 2 × 2 table of counts: the number of participants in each of two groups who did and did not have some outcome. Baseline tables report them for binary characteristics, such as the number of women in each group, and trials report them for adverse events, such as the number of participants in each group who were hospitalised. From the four counts, the odds ratio (OR), its confidence interval, and the p-value of a test of the association between group and outcome can all be recalculated. As with the SMD, there is more than one defensible way to do each. The OR can be the sample OR (the product of the counts on one diagonal divided by the product of those on the other) or the conditional maximum likelihood estimate. Its confidence interval can be a Wald interval on the log scale, an exact interval, a mid-p exact interval, or a profile likelihood interval. The p-value can come from Pearson’s χ² test, with or without Yates’ continuity correction, a likelihood ratio test, or Fisher’s exact test, among others. And when one of the counts is zero, the sample OR and its Wald interval cannot be calculated unless a small number, usually 0.5, is first added to every cell.
This matters most for results that an article’s authors would rather not emphasise. Articles commonly test and report their intended benefits in detail, and describe harms only as counts, without an effect size or a test. A conclusion that a treatment is safe or well tolerated can then be checked by recalculating what the counts imply. Palhano-Fontes et al. (2019) concluded that their trial of ayahuasca for treatment-resistant depression “brings new evidence supporting the safety and therapeutic value of psychedelics”, but 4 of the 15 participants in the ayahuasca group were hospitalised, compared with none of the 15 in the placebo group (Elk & Fried, 2023). Strawn et al. (2023) concluded that escitalopram “reduced anxiety symptoms and was well tolerated” in children and adolescents with generalised anxiety disorder, but 13 of the 136 participants in the escitalopram group reported suicidal ideation, compared with 2 of the 137 in the placebo group (Plöderl et al., 2023).
The calculator below recalculates the OR, its 95% CI, and the p-value from a 2 × 2 table, using the recalc_oddsratio() function from {recalc} in your browser, loaded in the same way as in the other calculators in this chapter. Enter the four counts, and, optionally, whichever of the OR, its CI, and the p-value the article reports, to check whether they are consistent with the counts. A reported OR is also accepted if it is the reciprocal of the recalculated one, that is, if the article took the other group as the reference. The two examples load the counts above.
Many articles report descriptive statistics for the whole sample and for subgroups of it, such as by gender, site, or condition, often in the same table. The whole sample’s N, mean, and SD are determined exactly by the subgroups’ ns, means, and SDs, so the whole-sample values can be recalculated from the subgroups’ values and compared with the reported ones.
Cochrane Handbook’s formula for combining groups (Table 6.5.a in the current version). Note, not “pooled SD” since that term normally refers to the within-group-only SD used in t-tests and Cohen’s d, which ignores the mean differences.
Two groups:
\[ N = n_1 + n_2 \]
\[ M = \frac{n_1 M_1 + n_2 M_2}{N} \]
\[ SD = \sqrt{\frac{(n_1-1)SD_1^2 + (n_2-1)SD_2^2 + \frac{n_1 n_2}{N}(M_1 - M_2)^2}{N-1}} \]
k groups:
\[ SD^2 = \frac{\sum_i (n_i - 1) SD_i^2 + \sum_i n_i (M_i - M)^2}{N - 1} \]
As with p-values (Section 10.1.1.3), the comparison has to allow for rounding. A subgroup mean reported as 4.58 could have been anything from 4.575 to 4.585, so the recalculated whole-sample mean is not a single value but a range, and the reported whole-sample mean is consistent with the subgroups if the range of values that round to it overlaps the recalculated range. Sample sizes are the exception. They are counts, not rounded values, so the reported N must equal the sum of the subgroups’ ns exactly.
When the reported N is larger than the sum of the subgroups’ ns, the most innocent explanation is that some participants are missing from the breakdown: participants who did not report their gender, for example, or a small category that was left out of the table. If a single subgroup is missing, the same formulas can be rearranged to find the n, mean, and SD it would need to have for the reported whole-sample values to be correct.
Writing \(n_\star\), \(M_\star\), and \(SD_\star\) for the missing subgroup’s n, mean, and SD, and \(n_i\), \(M_i\), and \(SD_i\) for those of the reported subgroups:
\[ n_\star = N - \sum_i n_i \]
\[ M_\star = \frac{N M - \sum_i n_i M_i}{n_\star} \]
\[ SD_\star^2 = \frac{(N - 1) SD^2 - SS_i - n_\star (M_\star - M)^2}{n_\star - 1} \]
where \(SS_i = \sum_i (n_i - 1) SD_i^2 + \sum_i n_i (M_i - M)^2\) is the part of the whole sample’s sum of squares that belongs to the reported subgroups.
On a scale from min to max, the largest SD that a group of \(n_\star\) with mean \(M_\star\) can have is the Bhatia–Davis bound (Bhatia & Davis, 2000):
\[ SD_\star \leq \sqrt{\frac{n_\star}{n_\star - 1}(M_\star - min)(max - M_\star)} \]
These implied values can then be checked for whether they are possible at all. The implied variance can be negative, which no real group can have. The implied mean can fall outside the range of the scale. And the implied SD can be larger than any group of that size and mean could have on a bounded scale, a limit known as the Bhatia–Davis bound , Section 12.1.2. These are only the loosest bounds, and they are the only ones that the calculator below checks. If the scale is scored in whole numbers, the bounds are tighter: a missing subgroup of 6 can only have a mean that is a multiple of 1/6 (Section 11.2), and for each such mean its SD has a ceiling below the Bhatia–Davis bound and, unless the mean is itself a whole number, a floor above zero. The bounds methods in the {strait} package check these (Hussey, 2026). If the implied subgroup is impossible, a missing subgroup cannot explain the discrepancy. If it is possible, the explanation is plausible but not confirmed: the article may say elsewhere how many participants were left out of the breakdown, and why, which can be compared with the implied n.
The calculator below runs the recalc_total_from_subgroups() and recalc_missing_subgroup() functions from the {recalc} R package in your browser, using webR in the same way as the statcheck app (Section 10.1.1.1). Enter each subgroup’s n, mean, and SD, one subgroup per row. The means and SDs can be left empty if the article does not report them, in which case only the N is checked. You can paste a block of cells copied from a spreadsheet or a table, as in the SMD calculator (Section 10.2.1.2). Then, optionally, enter the whole-sample values that the article reports, and the minimum and maximum possible scores on the scale. Without reported whole-sample values, the calculator shows what they should be, given the subgroups. With them, it checks whether the reported values are consistent with the subgroups, and if the reported N is larger than the sum of the subgroups’ ns, it works out what a single unreported subgroup would need to be. The scale’s minimum and maximum are only used for this last step. The calculator handles up to 6 subgroups with SDs, and up to 12 without them, because the number of combinations of rounded values that it checks doubles with every value.
By default, the number of decimal places of the means and of the SDs is taken from the values as you typed them, so type 4.70 rather than 4.7 if the article reported two decimals. If values of the same kind were typed with different numbers of decimals, the fewest is used, which allows for the most rounding. Sample sizes are always taken as exact. {recalc} is not available as a webR package, so the calculator downloads the package’s R code from GitHub, at the version shown under the results. The starting values are simulated: a well-being scale scored from 1 to 7, reported for women and men, where 6 gender-diverse participants are included in the whole-sample values but not in the breakdown.
In the starting example, the reported N of 139 is 6 more than the 133 participants in the two subgroups, and the reported mean of 4.30 is not consistent with the subgroups’ means either: together, they give a whole-sample mean between 4.319 and 4.329. The reported SD is consistent with the subgroups’ SDs. A single unreported subgroup of 6 participants, with a mean between about 3.55 and 4.00 and an SD between about 0.41 and 1.48, would make all three reported values consistent, and such a subgroup is possible on a scale from 1 to 7. The 6 simulated gender-diverse participants had a mean of 3.83 and an SD of 1.33.
These ranges are wide because the missing subgroup is small. Rounding the whole-sample mean to two decimals leaves the sum of all 139 participants’ scores uncertain by up to ±0.7 (139 × 0.005), and the rounding of the two subgroups’ means adds almost as much again. All of this uncertainty falls on the 6 participants who are missing, so their mean can only be pinned down to within about ±0.23. Now change the reported SD to 1.75, or to 0.10. In both cases, no real subgroup of 6 could make the numbers consistent: its SD would have to be larger than any group’s could be on this scale, or its variance would have to be negative.