目的 複数のカテゴリー変数に基づいて多元分類を行い,各群のデータ数,平均値,標準偏差を求める。 さらに,一元分類の場合には一元配置分散分析またはクラスカル・ウォリス検定を行うこともできる。 使用法 breakdown(i, j, df, latex=TRUE, captions=NULL, labels=NULL, test=c("none", "parametric", "non-parametric"), var.equal=FALSE, digits=3, output="") 引数 i 分析対象となる変数が入っている列の番号または変数名ベクトル c 関数を使った複数指定可能 j 群を表す変数 factor の列番号または変数名ベクトル(一元分類を繰り返すのではなく,多元分類を行う) c 関数を使った複数指定可能 df 読み込んだデータフレームの名前 latex LaTeX ソースを出力する。Word 用なら,latex=FALSE にする captions latex=TRUE の場合,各表の表題を文字列ベクトルとして指定することができる(デフォルトではあり合わせの表題を付ける)。 labels latex=TRUE の場合,各表の label を文字列ベクトルとして指定することができる(デフォルトでは付けない)。 test 一元分類の場合には検定法を指定することができる。"parametric", "non-parametric" の何れか "parametric" の場合,2 群の場合には t.test 関数,3 群の場合には oneway.test 関数が呼ばれる "non-parametric" の場合,2 群の場合には wilcox.test 関数,3 群の場合には kruskal.test 関数が呼ばれる デフォルトは検定をしない var.equal oneway.test(t.test) の var.equal 引数として使用する digits 平均値,標準偏差を書き出すときに小数点以下何桁までにするかを指定 デフォルトでは 3 output 出力コネクション デフルトはコンソールに出力 ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/breakdown.R", encoding="euc-jp") ##### # # 複数のカテゴリー変数により多元分類を行い,各群の平均値,標準偏差を求め,必要なら平均値・代表値の差の検定を行う # ##### breakdown <- function(i, # 分析対象の変数が入っているデータフレーム上の列番号または変数名ベクトル j, # 群を表す変数が入っているデータフレーム上の列番号または変数名ベクトル df, # データフレーム latex=TRUE, # LaTeX 形式で集計表を出力する(デフォルトは LaTeX 形式) captions=NULL, # latex=TRUE のときに,各表の表題を表す文字列ベクトルを指定できる(NULL のときはデフォルトの表題) labels=NULL, # latex=TRUE のときに,各表の label を表す文字列ベクトルを指定できる(NULL のときは付けない) test=c("none", "parametric", "non-parametric"), # デフォルト none では検定を行わない。検定を行うときはその種類を指定する statistics=c("mean", "median"), # (平均値,標準偏差)を求めるか(中央値,四分偏差)を求めるかを指定する var.equal=FALSE, # t-test, oneway の場合に等分散性を仮定するかどうかの引数 digits=3, # 平均値,標準偏差を表示するときの小数点以下の桁数 output="", # ファイルに出力するときはファイル名(デフォルトはコンソールに出力) encoding=getOption("encoding")) # ファイルに出力するときのエンコーディング(デフォルトは OS による) { getNum <- function(str, df) { # 変数名から列番号を得る names <- colnames(df) seq_along(names)[names %in% str] } SIQ <- function(x) return(diff(fivenum(x)[c(2,4)])) # 四分偏差を求める下請け関数 if (output != "") { # 結果をファイルに出力する場合の処理 output <- file(output, open="w", encoding=encoding) } test <- match.arg(test) # 引数が省略形で与えられたときに,正確な名前をとる statistics <- match.arg(statistics) # 引数が省略形で与えられたときに,正確な名前をとる if (statistics == "mean") { MEAN <- mean # 位置の母数を求める関数:平均値 SD <- sd # 散布度を求める関数:標準偏差 M.str <- "平均値" S.str <- "標準偏差" } else { MEAN <- median # 位置の母数を求める関数:中央値 SD <- SIQ # 散布度を求める関数:四分偏差 M.str <- "中央値" S.str <- "四分偏差" } format <- paste("%.", digits, "f", sep="") # 小数点以下 3 桁で出力する書式 if (is.character(i[1])) { i <- getNum(i, df) } if (is.character(j[1])) { j <- getNum(j, df) } index <- 0 for (k in i) { # ベクトルで指定されたすべての変数について分析する ok <- complete.cases(df[,k], df[,j]) # 欠損値を持たないケースを特定 df2 <- df[ok,] # 欠損値を持つケースを除く nl <- length(j) # 何元分類にwなるか lst <- if (nl == 1) list(df2[,j]) else as.list(append(NULL, df2[,j])) x <- df2[, k] # 分析対象変数 nt <- length(x) # 全体のデータ数 mt <- MEAN(x) # 全体の平均値 st <- SD(x) # 全体の標準偏差 nms <- as.matrix(cbind(aggregate(df2[,k], lst, length), # 各群のデータ数 aggregate(df2[,k], lst, MEAN)[,nl+1], # 各群の平均値 aggregate(df2[,k], lst, SD)[,nl+1])) # 各群の標準偏差を取り出し,行列形式にする nr <- nrow(nms) # 行数(分類数) nc <- ncol(nms) # 列数(分類詳細と,データ数,平均値,標準偏差) str <- paste(colnames(df2)[j], collapse=",") # 多元分類に使われる変数名のリスト if (latex) { # LaTeX 形式で集計結果を出力する index <- index+1 cat("\n\\begin{table}[htbp]\n", file=output) # \begin{table}[htbp] if (is.null(captions)) { cat(sprintf("\\caption{%s別の%sの集計}\n", # \caption{○○別の□□の集計} str, colnames(df2)[k]), file=output) } else { cat(sprintf("\\caption{%s}\n", captions[index]), file=output) # \caption{○○○○} } if (!is.null(labels)) { cat(sprintf("\\label{%s}\n", labels[index]), file=output) # \labels{○○○○} } cat("\\centering\n", file=output) # \centering cat("\\begin{tabular}{", rep("l", nc-3), # \begin{tabular}{l…ccc} \hline "ccc} \\hline\n", sep="", file=output) cat(rep("&", nc-3), # 分類に使用する変数分の & sprintf(" \\multicolumn{3}{c}{%s}\\\\ \\cline{%i-%i}\n", # 最後の3列を使って分析対象の変数名と罫線 colnames(df2)[k], nc-2, nc), file=output) cat(colnames(df2)[j], "データ数", M.str, S.str, # 分類変数名 & データ数 & 平均値 & 標準偏差 sep=" & ", file=output) cat("\\\\ \\hline\n", file=output) # \\ \hline for (l in 1:nr) { # 各分類ごとに, cat(nms[l,1:(nc-2)], # 分類基準,データ数,平均値,標準偏差 sprintf(format, as.numeric(nms[l, (nc-1):nc])), sep=" & ", file=output) cat("\\\\", file=output) # \\ if (l == nr) cat("\\hline\n", file=output) else cat("\n", file=output) # 最後の行なら \hline } cat(sprintf("\\multicolumn{%i}{l}{全体}", nc-3), # 全体について,データ数,平均値,標準偏差 nt, sprintf(format, mt), sprintf(format, st), sep=" & ", file=output) cat("\\\\ \\hline\n", file=output) # \\ \hline cat("\\end{tabular}\n", file=output) # \end{tabular} } else { # tab で区切って出力する cat("\n表 ", str, "別の", colnames(df2)[k], "の集計", # 表 ○○別の□□の集計 sep="", file=output) cat("\n", colnames(df2)[k], sep="\t", file=output, # 分析対象変数 fill=TRUE) cat(colnames(df2)[j], "データ数", M.str, S.str, # 分類変数名 データ数 平均値 標準偏差 sep="\t", file=output, fill=TRUE) for (l in 1:nr) { # 各分類ごとに, cat(nms[l,1:(nc-2)], sprintf(format, # 分類基準,データ数,平均値,標準偏差 as.numeric(nms[l, (nc-1):nc])), sep="\t", file=output, fill=TRUE) } cat("全体", nt, sprintf(format, mt), # 全体について,データ数,平均値,標準偏差 sprintf(format, st), sep="\t", file=output, fill=TRUE) } if (nr >= 2 && nl == 1) { # 一元分類のときのみ検定を行う if (latex && test != "none") { cat("\\\\ \\noindent\n", file=output) } if (nr == 2 && test == "parametric") { # 2 群の場合には t.test を呼ぶ res <- t.test(x~df2[,j], var.equal=var.equal) cat(sprintf(if (latex) "$t$値 = %.3f, 自由度 = %.3f, $P$値 = %.3f\n" else "t 値 = %.3f, 自由度 = %.3f, P 値 = %.3f\n", res$statistic, res$parameter, res$p.value), file=output) } else if (nr >= 3 && test == "parametric") { # 3 群以上の場合には oneway.test を呼ぶ res <- oneway.test(x~df2[,j], var.equal=var.equal) cat(sprintf(if (latex) "$F$値 = %.3f, 自由度 = (%i, %.3f), $P$値 = %.3f\n" else "F 値 = %.3f, 自由度 = (%i, %.3f), P 値 = %.3f\n", res$statistic, res$parameter[1], res$parameter[2], res$p.value), file=output) } else if (nr == 2 && test == "non-parametric") { # 2 群以上の場合には wilcox.test を呼ぶ res <- wilcox.test(x~df2[,j]) # マン・ホイットニーの U 検定 cat(sprintf(if (latex) "$U$ = %.3f, $P$値 = %.3f\n" else "U = %.3f, P 値 = %.3f\n", res$statistic, res$p.value), file=output) } else if (nr >= 3 && test == "non-parametric") { # 3 群以上の場合には kruskal.test を呼ぶ res <- kruskal.test(x~df2[,j]) cat(sprintf(if (latex) "$\\chi^2_{kw}$値 = %.3f, 自由度 = %i, $P$値 = %.3f\n" else "カイ二乗値(kw) = %.3f, 自由度 = %i, P 値 = %.3f\n", res$statistic, res$parameter, res$p.value), file=output) } } if (latex) { # LaTeX 形式で集計結果を出力する場合は, cat("\\end{table}\n", file=output) # \end{table} } } if (output != "") { # 結果をファイルに出力した場合の後始末 close(output) } } 使用例 男女 血液型 測定値1 測定値2 1 2 101.3 135.8 1 2 101.8 165.7 1 1 122.6 178.9 2 4 114.4 155.8 1 4 89.7 143.0 2 2 83.4 123.7 1 2 93.2 151.3 2 1 99.6 108.8 1 3 127.5 101.6 2 4 104.7 156.1 2 4 84.2 173.7 2 2 90.6 122.6 1 1 90.0 102.2 1 1 97.6 176.7 2 4 97.4 125.0 1 1 92.8 172.8 2 3 103.4 146.5 2 2 101.2 159.0 2 2 87.8 148.0 2 1 95.5 140.5 1 2 89.0 171.8 2 3 94.3 121.2 1 3 69.9 114.9 1 3 79.4 160.0 1 3 105.7 98.1 1 2 95.2 133.5 2 4 113.7 86.5 2 2 106.8 148.9 2 2 112.1 206.1 2 1 91.7 163.0 のようなファイル test.dat があるとする 入力と変数の定義 df <- read.table("test.dat", header=TRUE) df[,1] <- factor(df[,1], levels=1:2, labels=c("男", "女")) df[,2] <- factor(df[,2], levels=1:4, labels=c("A", "B", "O", "AB")) ファイルに出力するとき breakdown(3:4, 1, df, latex=FALSE, output="ファイル名") 出力結果例 latex=FALSE の場合 > breakdown(3:4, 1, df, latex=FALSE) 表 男女別の測定値1の集計 測定値1 男女 データ数 平均値 標準偏差 男 14 96.836 15.060 女 16 98.800 9.969 全体 30 97.883 12.413 表 男女別の測定値2の集計 測定値2 男女 データ数 平均値 標準偏差 男 14 143.307 29.535 女 16 142.838 28.217 全体 30 143.057 28.336 > breakdown(3:4, 2, df, latex=FALSE) 表 血液型別の測定値1の集計 測定値1 血液型 データ数 平均値 標準偏差 A 7 98.543 11.127 B 11 96.582 8.795 O 6 96.700 20.483 AB 6 100.683 12.465 全体 30 97.883 12.413 表 血液型別の測定値2の集計 測定値2 血液型 データ数 平均値 標準偏差 A 7 148.986 32.410 B 11 151.491 24.184 O 6 123.717 24.759 AB 6 140.017 30.792 全体 30 143.057 28.336 > breakdown(3:4, 1:2, df, latex=FALSE) 表 男女,血液型別の測定値1の集計 測定値1 男女 血液型 データ数 平均値 標準偏差 男 A 4 100.750 14.901 女 A 3 95.600 3.951 男 B 5 96.100 5.458 女 B 6 96.983 11.421 男 O 4 95.625 26.093 女 O 2 98.850 6.435 男 AB 1 89.700 NA 女 AB 5 102.880 12.570 全体 30 97.883 12.413 表 男女,血液型別の測定値2の集計 測定値2 男女 血液型 データ数 平均値 標準偏差 男 A 4 157.650 37.053 女 A 3 137.433 27.230 男 B 5 151.620 17.206 女 B 6 151.383 30.543 男 O 4 118.650 28.501 女 O 2 133.850 17.890 男 AB 1 143.000 NA 女 AB 5 139.420 34.388 全体 30 143.057 28.336 latex=TRUE(デフォルト)の場合 > breakdown(4, 1:2, df) \begin{table}[htbp] \caption{男女,血液型別の測定値2の集計} \begin{center} \begin{tabular}{lccc} \hline & \multicolumn{3}{c}{測定値2}\\ \cline{2-4} 男女 & 血液型 & データ数 & 平均値 & 標準偏差\\ \hline 男 & A & 4 & 157.650 & 37.053\\ 女 & A & 3 & 137.433 & 27.230\\ 男 & B & 5 & 151.620 & 17.206\\ 女 & B & 6 & 151.383 & 30.543\\ 男 & O & 4 & 118.650 & 28.501\\ 女 & O & 2 & 133.850 & 17.890\\ 男 & AB & 1 & 143.000 & NA\\ 女 & AB & 5 & 139.420 & 34.388\\\hline 全体 & 30 & 143.057 & 28.336\\ \hline \end{tabular} \end{center} \end{table}