ブレークダウン     Last modified: Dec 12, 2012

目的

複数のカテゴリー変数に基づいて多元分類を行い,各群のデータ数,平均値,標準偏差を求める。
さらに,一元分類の場合には一元配置分散分析またはクラスカル・ウォリス検定を行うこともできる。

使用法

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}


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI

Made with Macintosh