目的 生データに対して,等分散性の検定,一元配置分散分析と多重比較を行う all in one 関数。 使用法 oneway.ANOVA(x, g, verbose=TRUE) 引数 x 分析対象となる観察値のベクトル g 観察値がどの群に属するかを表すベクトル verbose デフォルトでは結果をプリントする ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/oneway-ANOVA.R", encoding="euc-jp") oneway.ANOVA <- function(x, g, verbose=TRUE) { # x: データベクトル,g: 群変数ベクトル # 基礎統計量 d <- data.frame(x, g, stringsAsFactors = TRUE) level <- levels(d$g) k <- length(level) n <- aggregate(x ~ g, d, length)[,2] N <- sum(n) Mean <- aggregate(x ~ g, d, mean)[,2] Var <- aggregate(x ~ g, d, var)[,2] SD <- aggregate(x ~ g, d, sd)[,2] SE <- SD/sqrt(n) result <- data.frame(水準=level, n, Mean, SD, "Mean-SD"=Mean-SD, "Mean+SD"=Mean+SD, SE, "Mean-SE"=Mean-SE, "Mean+SE"=Mean+SE, check.names=FALSE) # デザインプロット if (verbose) { x.pos <- seq_along(level) plot(x.pos, Mean, xlim=c(0.5, k+0.5), ylim=range(Mean-SD, Mean+SD), pch=16, xlab="", xaxt="n", ylab="") axis(1, at=x.pos, labels=level) arrows(x.pos, Mean-SD, x.pos, Mean+SD, length=0.10, angle=90, code=3, lty=3) arrows(x.pos, Mean-SE, x.pos, Mean+SE, length=0.05, angle=90, code=3, lwd=2) } # 等分散性の検定 r.bartlett <- bartlett.test(d$x, d$g) r.Levene <- Levene.test(d$x, d$g) r.eqvar <- data.frame(手法=c("Bartlett", "Levene"), 分布=c("chi square", "F"), 統計量=c(r.bartlett$statistic, r.Levene$statistic), 自由度=c(r.bartlett$parameter, sprintf("(%i, %i)", r.Levene$parameter[1], r.Levene$parameter[2])), "P 値"=c(r.bartlett$p.value, r.Levene$p.value)) # 分散分析(等分散性を仮定する) r.oneway <- oneway.test(x ~ g, d, var.equal=TRUE) gm <- mean(d$x) St <- sum((d$x-gm)^2) Sb <- sum(n*(Mean-gm)^2) Sw <- St-Sb SS <- c(Sb, Sw, St) df <- c(k-1, N-k, N-1) MS <- SS/df F <- c(MS[1]/MS[2], NA, NA) p <- c(pf(F[1], df[1], df[2], lower.tail=FALSE), NA, NA) MS[3] <- NA r.ANOVA <- data.frame(要因=c("級間", "級内", "全体"), 平方和=c(Sb, Sw, St), 自由度=df, 平均平方=MS, "F 値"=F, "P 値"=p, check.names=FALSE) # 分散分析(等分散性を仮定しない) r.Welch <- oneway.test(x ~ g, d) r.BF <- Brown.Forsythe.test(x, g) r.ANOVA2 <- data.frame(手法=c("Welch", "Brown-Forsythe"), "F 値"=c(r.Welch$statistic, r.BF$statistic), "第 1 自由度"=c(k-1, r.BF$parameter[1]), "第 2 自由度"=c(r.Welch$parameter[2], r.BF$parameter[2]), "P 値"=c(r.Welch$p.value, r.BF$p.value), check.names=FALSE) # 多重比較 r.tukey <- tukey(d$x, d$g)$Tukey lc <- t(sapply(rownames(r.tukey), function(s) as.integer(unlist(strsplit(s, ":"))))) diff <- Mean[lc[,2]]-Mean[lc[,1]] r.GH <- tukey(d$x, d$g, method="G")$Games.Howell r.multi <- data.frame(群1=level[lc[,1]], 群2=level[lc[,2]], 平均1=Mean[lc[,1]], 平均2=Mean[lc[,2]], 差=diff, 差の標準誤差=diff/r.tukey[,1], "t 値(Tukey)"=r.tukey[,1], "P 値"=r.tukey[,2], "t 値(Games-Howell)"=r.GH[,1], "自由度"=r.GH[,2], "P 値"=r.GH[,3], check.names=FALSE) if (verbose) { cat("\n基礎統計量\n\n") print(result, row.names=FALSE) cat("\n等分散性の検定\n\n") print(r.eqvar, row.names=FALSE) cat("\n分散分析(等分散性を仮定する)\n\n") print(r.ANOVA, row.names=FALSE) cat("\n分散分析(等分散性を仮定しない)\n\n") print(r.ANOVA2, row.names=FALSE) cat("\n多重比較\n\n") print(r.multi, row.names=FALSE) } invisible(list(result, r.eqvar, r.ANOVA, r.ANOVA2, r.multi)) } 他に,以下の 3 つの関数も必要 インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/Brown-Forsythe-test.R", encoding="euc-jp") Brown.Forsythe.test <- function(x, group) { # x: データベクトル,group: 群変数ベクトル data.name <- paste(deparse(substitute(x)), "~", deparse(substitute(group))) OK <- complete.cases(x, group) # 欠損値を持つケースを除く x <- x[OK] group <- as.factor(group[OK]) group <- group[, drop=TRUE] d <- split(x, group) df1 <- length(d)-1 ni <- sapply(d, length) mi <- sapply(d, mean) ui <- sapply(d, var) ci <- (1-ni/sum(ni))*ui F.BF <- sum(ni*(mi-mean(x))^2)/sum(ci) C <- ci/sum(ci) df2 <- 1/sum(C^2/(ni-1)) p <- pf(F.BF, df1, df2, lower.tail=FALSE) method <- "Brown-Forsythe 検定" return(structure(list(statistic=c(F=F.BF), parameter=c("df1"=df1, "df2"=df2), "p.value"=p, method=method, data.name=data.name), class="htest")) } インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/levene-test.R", encoding="euc-jp") # 等分散性の検定 Levene.test <- function(x, # データベクトル group, # 群変数ベクトル method = c("mean", "median")) # 検定統計量の計算方法 { data.name <- paste(deparse(substitute(x)), "~", deparse(substitute(group))) OK <- complete.cases(x, group) # 欠損値を持つケースを除く x <- x[OK] fac <- as.factor(group[OK]) fac <- fac[, drop=TRUE] n <- length(x) # 全体のデータ個数 n.i <- tapply(x, fac, length) # 各群のデータ個数 k <- length(n.i) # 群の数 method <- match.arg(method) # 引数の補完 x <- abs(x-tapply(x, fac, method)[fac]) # 測定値からそのデータが属する群の平均値(または中央値)を差し引く sw <- sum((n.i-1)*tapply(x, fac, var)) # 群内変動 dfw <- n-k # 群内変動の自由度 dfb <- k-1 # 群間変動の自由度 f <- ((var(x)*(n-1)-sw)/dfb)/(sw/dfw) # 検定統計量 P <- pf(f, dfb, dfw, lower.tail=FALSE) # P 値 method <- paste("等分散性の検定(", method, " で調整)", sep="") return(structure(list(statistic=c(F=f), parameter=c("df b"=dfb, "df w"=dfw), p.value=P, method=method, data.name=data.name), class="htest")) } インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/tukey.R", encoding="euc-jp") # Tukey の方法による多重比較 # Games-Howell の方法も選択できるように拡張 2009/08/03 tukey <- function( data, # 観察値ベクトル group, # 群変数ベクトル method=c("Tukey", "Games-Howell")) # 手法の選択 { OK <- complete.cases(data, group) # 欠損値を持つケースを除く data <- data[OK] group <- factor(group[OK]) n <- tapply(data, group, length) # 各群のケース数 a <- length(n) # 群の数 phi.e <- sum(n)-a # 誤差分散(群内不偏分散)の自由度 Mean <- tapply(data, group, mean) # 各群の平均値 Variance <- tapply(data, group, var) # 各群の不偏分散 result1 <- cbind(n, Mean, Variance) # 各群の統計量 rownames(result1) <- paste("Group", 1:a, sep="") method <- match.arg(method) if (method == "Tukey") { # Tukey の方法 v.e <- sum((n-1)*Variance)/phi.e # 誤差分散(群内不偏分散) t <- combn(a, 2, function(ij) # 対比較 abs(diff(Mean[ij]))/sqrt(v.e*sum(1/n[ij])) ) p <- ptukey(t*sqrt(2), a, phi.e, lower.tail=FALSE) # 有意確率を計算する Tukey <- cbind(t, p) # 対比較の結果 rownames(Tukey) <- combn(a, 2, paste, collapse=":") return(list(result1=result1, Tukey=Tukey, phi=phi.e, v=v.e)) } else { # Games-Howell の方法 t.df <- combn(a, 2, function(ij) { # 対比較 t <- abs(diff(Mean[ij]))/sqrt(sum(Variance[ij]/n[ij])) df <- sum(Variance[ij]/n[ij])^2/sum((Variance[ij]/n[ij])^2/(n[ij]-1)) return(c(t, df))} ) t <- t.df[1,] df <- t.df[2,] p <- ptukey(t*sqrt(2), a, df, lower.tail=FALSE) # 有意確率を計算する Games.Howell <- cbind(t, df, p) # 対比較の結果 rownames(Games.Howell) <- combn(a, 2, paste, collapse=":") return(list(result1=result1, Games.Howell=Games.Howell)) } } 使用例 > x <- c( 205, 206, 164, 190, 194, 203, 201, 221, 197, 185, 248, 265, 197, 220, 212, 281, 202, 276, 237, 254, 230 ) > g <- rep(paste("A", 1:4, sep=""), c(6, 4, 6, 5)) > oneway.ANOVA(x, g) 基礎統計量 水準 n Mean SD Mean-SD Mean+SD SE Mean-SE Mean+SE A1 6 193.6667 15.88290 177.7838 209.5496 6.484169 187.1825 200.1508 A2 4 201.0000 14.96663 186.0334 215.9666 7.483315 193.5167 208.4833 A3 6 237.1667 32.72563 204.4410 269.8923 13.360181 223.8065 250.5268 A4 5 239.8000 27.58985 212.2101 267.3899 12.338557 227.4614 252.1386 等分散性の検定 手法 分布 統計量 自由度 P.値 Bartlett chi square 3.31855 3 0.3450692 Levene F 2.38566 (3, 17) 0.1050173 分散分析(等分散性を仮定する) 要因 平方和 自由度 平均平方 F 値 P 値 級間 9284.271 3 3094.7571 5.091555 0.01072138 級内 10332.967 17 607.8216 NA NA 全体 19617.238 20 NA NA NA 分散分析(等分散性を仮定しない) 手法 F 値 第 1 自由度 第 2 自由度 P 値 Welch 4.927451 3 8.860454 0.02766496 Brown-Forsythe 5.440656 3 13.322350 0.01163382 多重比較 群1 群2 平均1 平均2 差 差の標準誤差 t 値(Tukey) P 値 t 値(Games-Howell) A1 A2 193.6667 201.0000 7.333333 15.91411 0.4608069 0.96656131 0.7406106 A1 A3 193.6667 237.1667 43.500000 14.23402 3.0560597 0.03276031 2.9291841 A1 A4 193.6667 239.8000 46.133333 14.92876 3.0902319 0.03058705 3.3097548 A2 A3 201.0000 237.1667 36.166667 15.91411 2.2726160 0.14395624 2.3617950 A2 A4 201.0000 239.8000 38.800000 16.53843 2.3460508 0.12655164 2.6887452 A3 A4 237.1667 239.8000 2.633333 14.92876 0.1763933 0.99797118 0.1447992 自由度 P 値 6.871719 0.87779880 7.231682 0.07993964 6.139828 0.05810207 7.413345 0.16830990 6.340133 0.12046051 8.990836 0.99883370