47
$\begingroup$

Let's say we have the statistics given below

gender mean sd n
f 1.666667 0.5773503 3
m 4.500000 0.5773503 4

How do you perform a two-sample t-test (to see if there is a significant difference between the means of men and women in some variable) using statistics like this rather than actual data?

I couldn't find anywhere on the internet how to do this. Most of the tutorials and even the manual deal with the test with the actual data set only.

$\endgroup$
3
  • 2
    $\begingroup$ This Wikipedia article plus the help page for R's t-distribution functions (got by ?pt) -- see especially pt() -- do have all the info you'd need to do this yourself. And you'll learn a lot about stats and R if you do that. $\endgroup$ Commented Jun 13, 2012 at 16:40
  • 4
    $\begingroup$ There are good answers here already, and indeed it's both very easy (and good practice) to write a function for this yourself; however, I'll just add that you might take a look at the tsum.test function in package BSDA, which implements a t-test (two sample; Welch or equal-variance and also one sample) from summary data you supply. It basically works like the t-test in vanilla R but on the summary info. $\endgroup$
    – Glen_b
    Commented Jun 18, 2013 at 0:30
  • 3
    $\begingroup$ To be honest, when I was learning to program my teacher always said, "don't re-invent the wheel". Therefore, the most logical function would be tsum.test() from the BSDA library as stated by @Nick Cox. It does exactly the same thing as what @macro wrote in lines of code. If the question asked, what is the understanding of the background calculation for computing the t-test statistic in R then Marco would be more appropriate an answer. Please note, I am not trying to offend anyone, just stating my personal opinion related to my professional background. And @marco that is some neat coding :) $\endgroup$
    – tcratius
    Commented Aug 19, 2018 at 9:23

5 Answers 5

60
$\begingroup$

You can write your own function based on what we know about the mechanics of the two-sample $t$-test. For example, this will do the job:

# m1, m2: the sample means
# s1, s2: the sample standard deviations
# n1, n2: the same sizes
# m0: the null value for the difference in means to be tested for. Default is 0. 
# equal.variance: whether or not to assume equal variance. Default is FALSE. 
t.test2 <- function(m1,m2,s1,s2,n1,n2,m0=0,equal.variance=FALSE)
{
    if( equal.variance==FALSE ) 
    {
        se <- sqrt( (s1^2/n1) + (s2^2/n2) )
        # welch-satterthwaite df
        df <- ( (s1^2/n1 + s2^2/n2)^2 )/( (s1^2/n1)^2/(n1-1) + (s2^2/n2)^2/(n2-1) )
    } else
    {
        # pooled standard deviation, scaled by the sample sizes
        se <- sqrt( (1/n1 + 1/n2) * ((n1-1)*s1^2 + (n2-1)*s2^2)/(n1+n2-2) ) 
        df <- n1+n2-2
    }      
    t <- (m1-m2-m0)/se 
    dat <- c(m1-m2, se, t, 2*pt(-abs(t),df))    
    names(dat) <- c("Difference of means", "Std Error", "t", "p-value")
    return(dat) 
}

Example usage:

set.seed(0)
x1 <- rnorm(100)
x2 <- rnorm(200) 
# you'll find this output agrees with that of t.test when you input x1,x2
(tt2 <- t.test2(mean(x1), mean(x2), sd(x1), sd(x2), length(x1), length(x2)))

Difference of means       Std Error               t         p-value 
         0.01183358      0.11348530      0.10427416      0.91704542 

This matches the result of t.test:

(tt <- t.test(x1, x2))

#         Welch Two Sample t-test
#   
#   data:  x1 and x2
#   t = 0.10427, df = 223.18, p-value = 0.917
#   alternative hypothesis: true difference in means is not equal to 0
#   95 percent confidence interval:
#    -0.2118062  0.2354734
#   sample estimates:
#    mean of x  mean of y 
#   0.02266845 0.01083487 

tt$statistic == tt2[["t"]]
#        t 
#     TRUE 

tt$p.value == tt2[["p-value"]]
# [1] TRUE
$\endgroup$
4
  • 3
    $\begingroup$ My edit comparing to t.test got rejected, so here's some code to confirm: (tt2 <- t.test2(mean(x1), mean(x2), sd(x1), sd(x2), length(x1), length(x2))); (tt <- t.test(x1, x2)); tt$statistic == tt2[["t"]]; tt$p.value == tt2[["p-value"]] $\endgroup$
    – Max Ghenis
    Commented Nov 8, 2017 at 2:02
  • 1
    $\begingroup$ @MaxGhenis I re-added your edit. Seemed good to me. $\endgroup$
    – dfrankow
    Commented Jul 1, 2020 at 16:15
  • $\begingroup$ How would I modify this if I have the standard error, rather than the standard deviation? $\endgroup$
    – Adam_G
    Commented Dec 16, 2022 at 0:43
  • $\begingroup$ @Adam_G Did try to modify the code to compute via standard error. I am assuming you just use: SE = SD/√(sample size). So in the answer code, you would just remove the sample number n Can anyone confirm? $\endgroup$
    – jack kelly
    Commented Nov 27, 2023 at 19:05
24
$\begingroup$

You just calculate it by hand: $$ t = \frac{(\text{mean}_f - \text{mean}_m) - \text{expected difference}}{SE} \\ ~\\ ~\\ SE = \sqrt{\frac{sd_f^2}{n_f} + \frac{sd_m^2}{n_m}} \\ ~\\ ~\\ \text{where, }~~~df = n_m + n_f - 2 $$

The expected difference is probably zero.

If you want the p-value simply use the pt() function:

pt(t, df)

Thus, putting the code together:

> p = pt((((1.666667 - 4.500000) - 0)/sqrt(0.5773503/3 + 0.5773503/4)), (3 + 4 - 2))
> p
[1] 0.002272053

This assumes equal variances which is obvious because they have the same standard deviation.

$\endgroup$
2
  • $\begingroup$ A couple things: How is this "in R"? What is the distribution of the test statistic (i.e. how do you go from this to $p$-values)? $\endgroup$
    – Macro
    Commented Jun 14, 2012 at 14:04
  • 1
    $\begingroup$ The degree freedom provided in this case is incorrect! You use unpooled variance which assumes unequal variances. Thus, the degree of freedom is more accurate using Scatterwaite Approximation. $\endgroup$
    – lzstat
    Commented Oct 19, 2019 at 0:26
8
$\begingroup$

You can do the calculations based on the formula in the book (on the web page), or you can generate random data that has the properties stated (see the mvrnorm function in the MASS package) and use the regular t.test function on the simulated data.

$\endgroup$
2
  • $\begingroup$ When you say "you can generate random data that has the properties stated", do you mean simulating data with population mean and standard deviation equal to the sample values or simulating under the constraint that the sample mean and standard deviation are equal to a pre-specified value? $\endgroup$
    – Macro
    Commented Jun 14, 2012 at 14:05
  • 2
    $\begingroup$ You want the simulated data to have the exact same mean(s) and var(s) as stated in the problem. One way to do this (there are many others) is to use the mvrnorm function in the MASS package (you need to set the empirical argument to TRUE). $\endgroup$
    – Greg Snow
    Commented Jun 15, 2012 at 17:45
2
$\begingroup$

The question asks about R, but the issue can arise with any other statistical software. Stata for example has various so-called immediate commands, which allow calculations from summary statistics alone. See http://www.stata.com/manuals13/rttest.pdf for the particular case of the ttesti command, which applies here.

$\endgroup$
2
$\begingroup$

Another possible solution is to simulate the datasets and then use the standard t test function. It may be less efficient, computationally speaking, but it is very simple.

t.test.from.summary.data <- function(mean1, sd1, n1, mean2, sd2, n2, ...) {
    data1 <- scale(1:n1)*sd1 + mean1
    data2 <- scale(1:n2)*sd2 + mean2
    t.test(data1, data2, ...)
}

Given that the t test depends only on the sample summary statistics but disregards the actual sample distributions, this function will give exactly the same results (except for variable names) as the t test function:

x <- c(1.0, 1.2, 2.3, 4.2, 2.1, 3.0, 1.9, 2.0, 3.2, 1.6)
y <- c(3.5, 4.2, 3.3, 2.0, 1.7, 4.5, 2.7, 2.8, 3.3)
m_x <- mean(x)
m_y <- mean(y)
s_x <- sd(x)
s_y <- sd(y)
t.test.from.summary.data(m_x, s_x, 10, m_y, s_y, 9)

    Welch Two Sample t-test

data:  data1 and data2
t = -1.9755, df = 16.944, p-value = 0.06474
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.78101782  0.05879559
sample estimates:
mean of x mean of y 
 2.250000  3.111111 

t.test(x,y)

    Welch Two Sample t-test

data:  x and y
t = -1.9755, df = 16.944, p-value = 0.06474
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.78101782  0.05879559
sample estimates:
mean of x mean of y 
 2.250000  3.111111
$\endgroup$

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