多重クロス集計     Last modified: Feb 14, 2014

目的

ftable 関数が返す多重クロス集計のオブジェクトにより,多重クロス集計表をパーセント付きで LaTeX ソースとして出力する。

使用法

xtable.ftable(obj, caption="caption", label="label", percentage=c("row", "col", "none"), same.line=TRUE,
              percentage.font=c("small", "footnotesize", "tiny", "normalsize"),
              position=c("c", "r", "l"), rev=-1.5, booktabs=FALSE)

引数

obj                                 ftable などが返す ftable オブジェクト
caption="caption"                   キャプション
label="label"                       ラベル
percentage=c("row", "col", "none")  % を付ける方向
same.line=TRUE                      % を度数と同じ行に付けるときは TRUE にする
percentage.font=c("small", "footnotesize", "tiny", "normalsize") 
                                    LaTeX でのフォントサイズの指定 tiny, footnotesize など
position=c("c", "r", "l")           フィールド内での配置 "c", "r", "l" のいずれか
rev=-1.5                            行間を詰めるための,逆改行の大きさをミリ単位で指定(逆改行しない場合には 0 を指定する)
booktabs=FALSE                      TRUE なら \hline の代わりに \toprule, \midrule, \bottomrule を使う

ソース

インストールは,以下の 1 行をコピーし,R コンソールにペーストする
source("http://aoki2.si.gunma-u.ac.jp/R/src/xtable-ftable.R", encoding="euc-jp")

xtable.ftable <- function(   obj,                            # crosstabsn が返す ftable オブジェクト
                        caption="caption",                      # キャプション
                        label="label",                  # ラベル
                        percentage=c("row", "col", "none"),     # % を付ける方向
                        same.line=TRUE,                         # % を度数と同じ行に付けるときは TRUE にする
                        percentage.font=c("small", "footnotesize", "tiny", "normalsize"), # LaTeX でのフォントサイズの指定 tiny, footnotesize など
                        position=c("c", "r", "l"),              # フィールド内での配置 "c", "r", "l" のいずれか
                        rev=-1.5,                               # 行間を詰めるための,逆改行の大きさをミリ単位で指定(逆改行しない場合には 0 を指定する)
                        booktabs=FALSE)                 # TRUE なら \hline の代わりに \toprule, \midrule, \bottomrule を使う
# ftable 関数が返した ftable クラスのオブジェクトを入力し,LaTeX ソースを出力する
# formula で指定する。~ の左辺には1個のみ指定できる
# Sweave から使用するのが便利
# 使用例
# Titanic
# x <- ftable(Survived ~ ., data = Titanic)
# a <- ftable(Survived ~ Sex + Class + Age, data = x)
# xtable(a)
# xtable(ftable(Survived ~ Sex + Class, data = x))

{       row.vars <- attr(obj, "row.vars")
        n.row.vars <- length(row.vars)
        names.row.vars <- names(row.vars)
        m.row.vars <- sapply(row.vars, length)
        col.vars <- attr(obj, "col.vars")
        n.col.vars <- length(col.vars)
        names.col.vars <- names(col.vars)
        m.col.vars <- sapply(col.vars, length)
        if (n.col.vars != 1) {
                stop("col.vars が 1 変数の ftable オブジェクトしか扱えません")
        }
        nrow <- nrow(obj)
        side <- matrix("", nrow, n.row.vars)
        n.block <- nrow/m.row.vars[n.row.vars]
        side[, n.row.vars] <- unlist(rep(row.vars[n.row.vars], n.block))
        for (i in seq_len(n.row.vars-1)) {
                every <- prod(m.row.vars[(i+1):n.row.vars])
                side[(0:(nrow-1))%%every==0, i] <- unlist(row.vars[i])
        }

        percentage <- match.arg(percentage)
        if (percentage == "none") {
                same.line <- FALSE
        }
        percentage.font <- match.arg(percentage.font)
        position <- match.arg(position)

        if (booktabs) {
                toprule <- "\\toprule"
                midrule <- "\\midrule"
        }
        else {
                toprule <- midrule <- "\\hline"
        }

        col.vars <- c(unlist(col.vars[[1]]), "合計")
        fac <- same.line+1
        if (same.line) {
                pos <- c(rep(position, n.row.vars), rep(paste(position, "@{}", position), m.col.vars+1))
                header <- paste(paste(names.row.vars, collapse=" & "), paste("&", paste(col.vars, "\\%", sep=" & ", collapse=" & ")))
                fmt <- sprintf("%%d & {\\%s \\textit{%%6.1f}}", percentage.font)
        }
        else {
                pos <- rep(position, m.col.vars+1+n.row.vars)
                header <- paste(paste(names.row.vars, collapse=" & "), paste(col.vars, collapse=" & "), sep=" & ")
                fmt <- sprintf("{\\%s \\textit{%%5.1f}}", percentage.font)
        }
        cat("\\begin{table}[htbp]\n",
            "\\caption{", caption, "}\n",
            "\\label{", label, "}\n",
            "\\centering\n",
            "\\begin{tabular}{", pos, "} ", toprule, " \n", sep="")
        cat(paste(rep("&", n.row.vars), collapse=" "))
        cat(sprintf(" \\multicolumn{%i}{c}{%s}\\\\ \\cline{%i-%i}\n",
            fac*m.col.vars[1], names.col.vars[1], n.row.vars+1, fac*m.col.vars[1]+n.row.vars))
        cat(header, " \\\\ ", midrule, "\n", sep="")

        for (k in 1:n.block) {
                end <- k*m.row.vars[n.row.vars]
                begin <- end-m.row.vars[n.row.vars]+1
                block <- addmargins(obj[begin:end, ])
                side.block <- rbind(side[begin:end, , drop=FALSE ], c(rep("", n.row.vars-1), "合計"))
                if (percentage == "row") {
                        pct <- block/block[, m.col.vars+1]*100
                }
                else {
                        pct <- t(t(block)/block[m.row.vars[n.row.vars]+1,]*100)
                }
                n <- m.row.vars[n.row.vars]+1
                for (i in 1:n) {
                        cat(sprintf("%s &", side.block[i,]))
                        if (same.line) {
                                cat(gsub("NaN", "---", paste(apply(cbind(block[i,], pct[i,]), 1, function(y) sprintf(fmt, y[1], y[2])), collapse=" & ")))
                        }
                        else {
                                cat(paste(block[i,], collapse=" & "), "\\\\ \n")
                                if (percentage != "none") {
                                        cat(rep(" &", n.row.vars-1))
                                        cat("\\%", gsub("NaN", "---", sprintf(fmt, pct[i, ])), sep=" & ")
                                }
                        }
                        if (percentage != "none") {
                                cat(" \\\\")
                        }
                        if (i < n-1) {
                                cat(sprintf("[%smm]\n", rev))
                        }
                        else if (i == n) {
                                if (end < nrow) {
                                        cat(sprintf("\\cline{%i-%i}\n", sum(side[end+1,] == "")+1, fac*(m.col.vars[1]+1)+n.row.vars))
                                }
                                else {
                                        cat(sprintf("%s\n", toprule))
                                }
                        }
                        else {
                                cat(sprintf("\\cline{%i-%i}\n", n.row.vars, fac*(m.col.vars[1]+1)+n.row.vars))
                        }
                }
        }
        cat("\\end{tabular}\n",
            "\\end{table}\n", sep="")
}


使用例

# x <- ftable(Survived ~ ., data = Titanic)
# a <- ftable(Survived ~ Sex + Class + Age, data = x)
# library(xtable)
# xtable(a, "タイタニックデータの集計(1)", "table1")
# xtable(ftable(Survived ~ Sex + Class, data = x), "タイタニックデータの集計(2)", "table2")
LaTeX でタイプセットすると以下のようになる。

LaTeX 出力

LaTeX 出力


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

Made with Macintosh