[R] Are multiple range tests (Duncan, Bonferroni, Tukey, ...) available in R?

Douglas Bates bates at stat.wisc.edu
Sat May 6 00:48:32 CEST 2000


Ko-Kang Wang <Ko-Kang at xtra.co.nz> writes:

> Yes, even as an undergraduate student taking a paper on experimental
> design, I found this problem a while ago.
> 
> I am trying to use the current ANOVA table function and
> model.tables, extend them to get LSD, LSD_B, Tukey...etc directly.
> However since I've never written an R package before (done some
> single R functions though), it may take some time to do so.
> 
> By the way, have you tried model.tables()?  You can, I think
> sometimes anywa, get SED from this function.

Thanks for the hint of looking at model.tables().  Since V&R refer to
its only being available in S-PLUS 4.0 and later, I had neglected to
look for it in R.

That function does a lot of the heavy lifting for the multiple
comparisons calculations.  I had been promising my statistics class a
function to do Tukey multiple comparisons and I now have a draft
version enclosed below.  I would appreciate comments on it, especially
if I have the calculations wrong.  I think they are correct but I
would appreciate confirmation.

The function returns a set of confidence intervals on the differences
of the means for the levels of the factors.  If the optional argument
`order' is TRUE the levels of the factor are first put in increasing
order so the `diff' column of the result will be positive and you can
check which pairs of levels are significantly different by checking
which entries in the `lwr' column are positive.

The calculation is designed to accomodate unbalanced designs and
multiple factors.  It is not guaranteed that multiple comparisons will
always make sense in those cases. A sample usage is shown first.

 > library(Devore5)
 > data(xmp10.01)
 > fm1 <- aov(strength ~ type, data = xmp10.01)
 > summary(fm1)
	     Df Sum Sq Mean Sq F value    Pr(>F)    
 type         3 127375   42458  25.094 5.525e-07 ***
 Residuals   20  33839    1692                      
 ---
 Signif. codes:  0  `***'  0.001  `**'  0.01  `*'  0.05  `.'  0.1  ` '  1 
 > model.tables(fm1, "means", se = TRUE)
 Tables of means
 Grand mean

 682.5042 

  type 
     A     B     C     D 
 713.0 756.9 698.1 562.0 

 Standard errors for differences of means
	  type
	 23.75
 replic.     6
 > Tukey(fm1)
 $type
	   diff        lwr         upr
 B-A   43.93333  -22.53671  110.403377
 C-A  -14.93333  -81.40338   51.536711
 D-A -150.98333 -217.45338  -84.513289
 C-B  -58.86667 -125.33671    7.603377
 D-B -194.91667 -261.38671 -128.446623
 D-C -136.05000 -202.52004  -69.579956

 attr(,"class")
 [1] "Tukey"
 > Tukey(fm1, order = TRUE)
 $type
	  diff        lwr       upr
 C-D 136.05000  69.579956 202.52004
 A-D 150.98333  84.513289 217.45338
 B-D 194.91667 128.446623 261.38671
 A-C  14.93333 -51.536711  81.40338
 B-C  58.86667  -7.603377 125.33671
 B-A  43.93333 -22.536711 110.40338

 attr(,"class")
 [1] "Tukey"

### $Id: Tukey.R,v 1.1 2000/05/05 22:31:21 bates Exp $
###
###               Tukey multiple comparisons for R
###
### Copyright 2000-2000  Douglas M. Bates <bates at stat.wisc.edu>
###
### This file is made available under the terms of the GNU General
### Public License, version 2, or at your option, any later version,
### incorporated herein by reference.
###
### This program is distributed in the hope that it will be
### useful, but WITHOUT ANY WARRANTY; without even the implied
### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
### PURPOSE.  See the GNU General Public License for more
### details.
###
### You should have received a copy of the GNU General Public
### License along with this program; if not, write to the Free
### Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
### MA 02111-1307, USA

Tukey <- function(x, ...) UseMethod("Tukey")

Tukey.aov <-
    function(x, order = FALSE, conf.level = 0.95, ...)
{
    mm <- model.tables(x, "means")
    tabs <- mm$tables[-1]
    nn <- mm$n
    out <- vector("list", length(tabs))
    names(out) <- names(tabs)
    MSE <- sum(resid(x)^2)/x$df.residual
    for (nm in names(tabs)) {
        means <- as.vector(tabs[[nm]])
        nms <- names(tabs[[nm]])
        n <- nn[[nm]]
        ## expand n to the correct length if necessary
        if (length(n) < length(means)) n <- rep(n, length(means))
        if (as.logical(order)) {
            ord <- order(means)
            means <- means[ord]
            n <- n[ord]
            if (!is.null(nms)) nms <- nms[ord]
        }
        center <- outer(means, means, "-")
        keep <- lower.tri(center)
        center <- center[keep]
        width <- qtukey(conf.level, length(means), x$df.residual) *
            sqrt((MSE/2) * outer(1/n, 1/n, "+"))[keep]
        dnames <- list(NULL, c("diff", "lwr", "upr"))
        if (!is.null(nms)) dnames[[1]] <- outer(nms, nms, paste, sep = "-")[keep]
        out[[nm]] <- array(c(center, center - width, center + width),
                           c(length(width), 3), dnames)
    }
    class(out) <- "Tukey"
    out
}

-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list