Cross Validated is a question and answer site for people interested in statistics, machine learning, data analysis, data mining, and data visualization. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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)
share|improve this question
up vote 13 down vote accepted

Use pt and make it two-tailed.

> 2*pt(11.244, 30, lower=FALSE)
[1] 2.785806e-12
share|improve this answer
That was it. Thank you! – herbps10 Dec 5 '12 at 2:23
I think there is a detail missing: When to use lower=F? - Please see my question here:… – vonjd Jan 12 '15 at 11:28
The value needs to be positive, so if using this with a variable that could be negative, wrap in abs. – Aaron Jan 12 '15 at 16:14
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. – ashic Jul 23 '15 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?

share|improve this answer
Thanks for the reply! I just edited my post to include the full source code along with my sample dataset. – herbps10 Dec 5 '12 at 2:20
Thanks. Checked it but it was already resolved. – Glen_b Dec 5 '12 at 2:24
Good general response, thanks. – Aaron Dec 5 '12 at 3:14

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)!

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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