目的 単一のカテゴリー変数と複数の該当・非該当の応答のある変数のクロス集計を行う 使用法 ma(i, j, df, latex=TRUE, caption=NULL, label=NULL, output="") 引数 i, j データフレーム上で,クロス集計をする二変数が入っている,列の番号または変数名ベクトル 該当・非該当により答える項目は i, j のどちらに指定してもよい 実際には 1, 3:10 とか 12:17, 2 のように指定する 注意:データフレーム上で,該当・非該当のデータの定義を間違わないように(使用例参照) df 読み込んだデータフレームの名前 latex LaTeX ソースを出力する。Word 用なら,latex=FALSE にする caption latex=TRUE の場合,各表の表題を文字列ベクトルとして指定することができる(デフォルトではあり合わせの表題を付ける)。 label latex=TRUE の場合,各表の label を文字列ベクトルとして指定することができる(デフォルトでは付けない)。 output 出力コネクション デフルトはコンソールに出力 ソース インストールは,以下の 1 行をコピーし,R コンソールにペーストする source("http://aoki2.si.gunma-u.ac.jp/R/src/multianswer.R", encoding="euc-jp") ##### # # マルチアンサー項目と別の 1 つの変数についてクロス集計表を作成する # ##### ma <- function(i, # 表側に来る変数が入っているデータフレーム上の列番号または変数名ベクトル j, # 表側に来る変数が入っているデータフレーム上の列番号または変数名ベクトル # i, j いずれかがマルチアンサー項目を表すのでベクトルになる df, # データフレーム latex=TRUE, # LaTeX 形式で度数分布表を出力する(デフォルトは LaTeX 形式) caption=NULL, # latex=TRUE のときに,各表の表題を表す文字列ベクトルを指定できる(NULL のときはデフォルトの表題) label=NULL, # latex=TRUE のときに,各表の label を表す文字列ベクトルを指定できる(NULL のときは付けない) output="", # ファイルに出力するときはファイル名(デフォルトはコンソールに出力) encoding=getOption("encoding")) # ファイルに出力するときのエンコーディング(デフォルトは OS による) { # 下請け関数 is.error <- function(k) # k 列目の変数が factor であり,かつ,二値変数でなければならない { if (!is.factor(df[,k])) { # factor でない warning(sprintf("%s を factor にしてください", colnames(df)[k])) return(TRUE) } else if (nlevels(df[,k]) != 2) { # 二値変数でない warning(sprintf("%s が二値データではありません", colnames(df)[k])) return(TRUE) } return(FALSE) } getNum <- function(str, df) { # 変数名から列番号を得る names <- colnames(df) seq_along(names)[names %in% str] } # 関数本体 if (output != "") { # 結果をファイルに出力する場合の処理 output <- file(output, open="w", encoding=encoding) } if (is.character(i[1])) { i <- getNum(i, df) } if (is.character(j[1])) { j <- getNum(j, df) } if (length(i) == 1 && length(j) > 1) { # i の方が普通の変数(1 つ),j の方がマルチアンサー変数(複数)のとき row <- TRUE # 表頭にマルチアンサー項目,row = TRUE として識別 } else if (length(i) > 1 && length(j) == 1) { # i の方がマルチアンサー変数(複数),j の方が普通の変数(1 つ)のとき row <- FALSE # 表側にマルチアンサー項目,row = FALSE として識別 temp <- i # row == TRUE のときと同じように処理するために,i, j の内容を入れ替える i <- j j <- temp } else { # 普通の変数が複数個指定されるような場合は想定していない stop("このプログラムでは,i, j いずれかが要素 1 のスカラー,他方が要素2以上のベクトルであることを仮定しています。使用法に誤りがあります") } if (any(sapply(j, is.error))) stop("データの準備に問題があります") # マルチアンサー変数のチェック df.i <- as.factor(df[,i]) # 普通の変数の方も factor にされている方が望ましいが,そうではないときのために ans <- sapply(j, function(k) table(df[,i], df[,k]))[1:nlevels(df.i),] # マルチアンサー集計表本体を作る ans <- cbind(ans, table(df.i)) # 合計列を作る(普通の変数の方の度数分布) ans <- rbind(ans, colSums(ans)) # 合計行を作る rownames(ans) <- c(levels(df.i), "合計") # 行の名前 colnames(ans) <- c(colnames(df[,j]), "該当数") # 列の名前 nc <- ncol(ans) # 列数 pct <- ans/ans[,nc]*100 # 行方向パーセント if (!row) { # row == FALSE の場合に, ans <- t(ans) # ans を転置 pct <- t(pct) # pct を転置 nc <- ncol(ans) # 転置後の列数を再計算 } nr <- nrow(ans) # 最終時点の集計表の行数 if (latex) { # LaTeX 形式で集計結果を出力する cat("\\begin{table}[htbp]\n", file=output) # \begin{table}[htbp] if (is.null(caption)) { cat("\\caption{マルチアンサー項目の集計}\n", file=output) # \caption{マルチアンサー項目の集計} } else { cat(sprintf("\\caption{%s}\n", caption), file=output) # 指定した表題 } if (!is.null(label)) { cat(sprintf("\\label{%s}\n", label), file=output) # 指定したラベル } cat("\\centering\n", file=output) # \centering cat("\\begin{tabular}{l", rep("c", nc), "} \\hline\n", sep="", file=output) # \begin{tabular}{cc…c} \hline if (row) { # 表頭にマルチアンサー項目 cat(colnames(df)[i], colnames(ans), sep=" & ", file=output) # 変数名 & マルチアンサー変数i & … cat("\\\\ \\hline\n", file=output) # \\ \hline for (i in 1:nr) { # 各行について, cat(rownames(ans)[i], ans[i,], sep=" & ", file=output) # 行名 & 集計数i & … cat("\\\\\n", file=output) # \\ cat("\\%", sprintf("{\\small \\textit{%.1f}}", pct[i,-nc]), sep=" & ", file=output) # % & パーセントi & … cat("\\\\", file=output) # \\ if (i >= nr-1) cat("\\hline\n", file=output) else cat("\n", file=output) # 最終行の前なら \\ } } else { # 表側にマルチアンサー項目 cat(sprintf("& \\multicolumn{%i}{c}{%s}\\\\ \\cline{2-%i}\n", nc-1, colnames(df)[i], nc), # マルチアンサーではない方の変数名 file=output) cat("", colnames(ans), sep=" & ", file=output) # 列名(変数のカテゴリー名) cat("\\\\ \\hline\n", file=output) # \\ \hline for (i in 1:nr) { # 各行(マルチアンサー項目)ごとに, cat(rownames(ans)[i], ans[i,], sep=" & ", file=output) # 行名 & 集計数i & … cat("\\\\\n", file=output) # \\ if (i < nr) { # 最終行でないときは, cat("\\%", sprintf("{\\small \\textit{%.1f}}", pct[i,]), sep=" & ", file=output)# % & パーセントi & … cat("\\\\", file=output) # \\ } if (i >= nr-1) cat("\\hline\n", file=output) else cat("\n", file=output) # 最終行の前なら \\ } } cat("\\end{tabular}\n", file=output) # \end{tabular} cat("\\end{table}\n", file=output) # \end{table} } else { # tab で区切って出力する cat("表 マルチアンサー項目の集計\n", file=output) # マルチアンサー項目の集計 if (row) { cat("\n", file=output, fill=TRUE) cat(colnames(df)[i], colnames(ans), sep="\t", file=output, fill=TRUE) # 変数名 マルチアンサー変数i … for (i in 1:nr) { # 各行について, cat(rownames(ans)[i], ans[i,], sep="\t", file=output, fill=TRUE) # 行名 集計数i … cat("%", sprintf("%.1f", pct[i,-nc]), sep="\t", file=output, fill=TRUE) # % パーセントi … } } else { # 表側にマルチアンサー項目を置く場合 cat("\n", colnames(df)[i], sep="\t", file=output, fill=TRUE) # マルチアンサーではない方の変数名 cat("", colnames(ans), sep="\t", file=output, fill=TRUE) # 列名(変数のカテゴリー名) for (i in 1:nr) { # 各行(マルチアンサー項目)ごとに, cat(rownames(ans)[i], ans[i,], sep="\t", file=output, fill=TRUE) # 行名 集計数i … if (i < nr) { # 最終行でないときは, cat("%", sprintf("%.1f", pct[i,]), sep="\t", file=output, fill=TRUE) # % パーセントi … } } } } if (output != "") { # 結果をファイルに出力した場合の後始末 close(output) } } 使用例 性別 血液型 項目1 項目2 項目3 項目4 項目5 1 1 1 1 0 1 1 2 2 0 1 0 1 1 1 3 0 0 0 0 1 1 4 1 1 1 1 1 1 1 1 0 0 1 0 2 2 0 1 1 1 1 2 3 1 1 0 1 0 1 3 1 1 1 1 0 2 2 1 1 0 0 0 2 1 0 0 1 0 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")) 項目1〜項目5 は該当なら1,非該当なら0で入力されている 集計したいことを表す数値(この例なら「該当」)を levels の1番目の数値にすること for (i in 3:7) df[,i] <- factor(df[,i], levels=1:0, labels=c("該当", "非該当")) コンソールに出力するとき ma(2, 3:7, df) ファイルに出力するとき ma(2, 3:7, df, output="ファイル名", encoding="EUC-JP") 出力結果例 latex=FALSE の場合 > ma(2, 3:7, df, latex=FALSE) # 二番目の引数がマルチアンサー項目の場合 血液型 項目1 項目2 項目3 項目4 項目5 該当数 A 2 1 1 2 1 3 % 66.7 33.3 33.3 66.7 33.3 B 1 3 1 2 2 3 % 33.3 100.0 33.3 66.7 66.7 O 2 2 1 2 1 3 % 66.7 66.7 33.3 66.7 33.3 AB 1 1 1 1 1 1 % 100.0 100.0 100.0 100.0 100.0 合計 6 7 4 7 5 10 % 60.0 70.0 40.0 70.0 50.0 注:% は各項目に答えた数を右端にある該当数で割ったものである。 マルチアンサーのため,% を合計しても 100% にはならない。 > ma(3:7, 2, df, latex=FALSE) # 一番目の引数がマルチアンサー項目の場合 血液型 A B O AB 合計 項目1 2 1 2 1 6 % 66.7 33.3 66.7 100.0 60.0 項目2 1 3 2 1 7 % 33.3 100.0 66.7 100.0 70.0 項目3 1 1 1 1 4 % 33.3 33.3 33.3 100.0 40.0 項目4 2 2 2 1 7 % 66.7 66.7 66.7 100.0 70.0 項目5 1 2 1 1 5 % 33.3 66.7 33.3 100.0 50.0 該当数 3 3 3 1 10 注:% は各項目に答えた数を最下行にある該当数で割ったものである。 マルチアンサーのため,% を合計しても 100% にはならない。 latex=TRUE(デフォルト)の場合 > ma(2, 3:7, df) # 二番目の引数がマルチアンサー項目の場合 \begin{table}[htbp] \begin{center} \begin{tabular}{lcccccc} \hline 血液型 & 項目1 & 項目2 & 項目3 & 項目4 & 項目5 & 該当数\\ \hline A & 2 & 1 & 1 & 2 & 1 & 3\\ \% & {\small \textit{66.7}} & {\small \textit{33.3}} & {\small \textit{33.3}} & {\small \textit{66.7}} & {\small \textit{33.3}}\\ B & 1 & 3 & 1 & 2 & 2 & 3\\ \% & {\small \textit{33.3}} & {\small \textit{100.0}} & {\small \textit{33.3}} & {\small \textit{66.7}} & {\small \textit{66.7}}\\ O & 2 & 2 & 1 & 2 & 1 & 3\\ \% & {\small \textit{66.7}} & {\small \textit{66.7}} & {\small \textit{33.3}} & {\small \textit{66.7}} & {\small \textit{33.3}}\\ AB & 1 & 1 & 1 & 1 & 1 & 1\\ \% & {\small \textit{100.0}} & {\small \textit{100.0}} & {\small \textit{100.0}} & {\small \textit{100.0}} & {\small \textit{100.0}}\\\hline 合計 & 6 & 7 & 4 & 7 & 5 & 10\\ \% & {\small \textit{60.0}} & {\small \textit{70.0}} & {\small \textit{40.0}} & {\small \textit{70.0}} & {\small \textit{50.0}}\\\hline \end{tabular} \end{center} \end{table} > ma(3:7, 2, df) # 一番目の引数がマルチアンサー項目の場合 \begin{table}[htbp] \begin{center} \begin{tabular}{lccccc} \hline & \multicolumn{4}{c}{血液型}\\ \cline{2-5} & A & B & O & AB & 合計\\ \hline 項目1 & 2 & 1 & 2 & 1 & 6\\ \% & {\small \textit{66.7}} & {\small \textit{33.3}} & {\small \textit{66.7}} & {\small \textit{100.0}} & {\small \textit{60.0}}\\ 項目2 & 1 & 3 & 2 & 1 & 7\\ \% & {\small \textit{33.3}} & {\small \textit{100.0}} & {\small \textit{66.7}} & {\small \textit{100.0}} & {\small \textit{70.0}}\\ 項目3 & 1 & 1 & 1 & 1 & 4\\ \% & {\small \textit{33.3}} & {\small \textit{33.3}} & {\small \textit{33.3}} & {\small \textit{100.0}} & {\small \textit{40.0}}\\ 項目4 & 2 & 2 & 2 & 1 & 7\\ \% & {\small \textit{66.7}} & {\small \textit{66.7}} & {\small \textit{66.7}} & {\small \textit{100.0}} & {\small \textit{70.0}}\\ 項目5 & 1 & 2 & 1 & 1 & 5\\ \% & {\small \textit{33.3}} & {\small \textit{66.7}} & {\small \textit{33.3}} & {\small \textit{100.0}} & {\small \textit{50.0}}\\\hline 該当数 & 3 & 3 & 3 & 1 & 10\\ \hline \end{tabular} \end{center} \end{table}