I have a sample dataset with 31 values. I ran a two-tailed t-test using R to test if the true mean is equal to 10:

t.test(x=data, mu=10, conf.level=0.95)


t = 11.244, df = 30, p-value = 2.786e-12
alternative hypothesis: true mean is not equal to 10 
95 percent confidence interval:
 19.18980 23.26907 
sample estimates:
mean of x 

Now I'm trying to do the same thing manually:

t.value = (mean(data) - 10) / (sd(data) / sqrt(length(data))) 
p.value = dt(t.value, df=length(lengths-1))

The t-value calculated using this method is the same as output by the t-test R function. The p-value, however, comes out to be 3.025803e-12.

Any ideas what I'm doing wrong?



Here is the full R code, including my dataset:

# Raw dataset -- 32 observations
data = c(21.75, 18.0875, 18.75, 23.5, 14.125, 16.75, 11.125, 11.125, 14.875, 15.5, 20.875,
            17.125, 19.075, 25.125, 27.75, 29.825, 17.825, 28.375, 22.625, 28.75, 27, 12.825, 
            26, 32.825, 25.375, 24.825, 25.825, 15.625, 26.825, 24.625, 26.625, 19.625)

# Student t-Test
t.test(x=data, mu=10, conf.level=0.95)

# Manually calculate p-value
t.value = (mean(data) - 10) / (sd(data) / sqrt(length(data)))
p.value = dt(t.value, df=length(data) - 1)

4 Answers 4


Use pt and make it two-tailed.

> 2*pt(11.244, 30, lower=FALSE)
[1] 2.785806e-12
  • 1
    $\begingroup$ I think there is a detail missing: When to use lower=F? - Please see my question here: stats.stackexchange.com/questions/133091/… $\endgroup$
    – vonjd
    Commented Jan 12, 2015 at 11:28
  • 5
    $\begingroup$ The value needs to be positive, so if using this with a variable that could be negative, wrap in abs. $\endgroup$ Commented Jan 12, 2015 at 16:14
  • 4
    $\begingroup$ For a two tailed test, you're looking for the probability that the value is less than -11.244 or more than +11.244. lower=F tells R to compute the probability of the value being more than the first parameter. Otherwise, it gives you the probability of the value being less than the first parameter. As such, you could also do 2*pt(-11.244, 30). Personally, I usually do 2*pt(-abs(q), df=n-1) as R defaults to lower=T. $\endgroup$
    – ashic
    Commented Jul 23, 2015 at 2:33

I posted this as a comment but when I wanted to add a bit more in edit, it became too long so I've moved it down here.

Edit: Your test statistic and d.f are correct. The other answer notes the issue with the calculation of the tail area in the call to pt(), and the doubling for two-tails, which resolves your difference. Nevertheless I'll leave my earlier discussion/comment because it makes relevant points more generally about p-values in extreme tails:

It's possible you could be doing nothing wrong and still get a difference, but if you post a reproducible example it might be possible to investigate further whether you have some error (say in the df).

These things are calculated from approximations that may not be particularly accurate in the very extreme tail.

If the two things don't use identical approximations they may not agree closely, but that lack of agreement shouldn't matter (for the exact tail area out that far to be meaningful number, the required assumptions would have to hold to astounding degrees of accuracy). Do you really have exact normality, exact independence, exactly constant variance?

You shouldn't necessarily expect great accuracy out where the numbers won't mean anything anyway. To what extent does it matter if the calculated approximate p-value is $2\times 10^{-12}$ or $3\times 10^{-12}$? Neither number is measuring the actual p-value of your true situation. Even if one of the numbers did represent the real p-value of your true situation, once its below about $0.0001$, why would you care what that value actually was?


The best way to calculate it manually is:

t.value = (mean(data) - 10) / (sd(data) / sqrt(length(data))) 
p.value = 2*pt(-abs(t.value), df=length(data)-1)

You need the abs() function because otherwise you run the risk of getting p-values bigger than $1$ (when the mean of the data is bigger than the given mean)!


I really like the answer @Aaron provided, along with the abs comments. I find a handy confirmation is to run

pt(1.96, 1000000, lower.tail = F) * 2

which yields 0.04999607.

Here, we're using the well-known property that 95% of the area under the normal distribution occurs at ~1.96 standard deviations, thus the output of ~0.05 gives our p-value. I used 1000000 since when N is huge, the t distribution is nearly the same as the normal distribution. Running this gave me comfort in @Aaron's solution.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.