计数&百分比在xTable,Sweave,R,交叉表格
题
编辑:关大厦下面aL3xa的回答,我已经修改了以下语法。并不完美,但越来越近。我还没有找到一种方法,使xtable接受\多列{}论据列或行。还可以看出Hmisc处理某些类型的幕后工作的,但它看起来像一个有点事业的理解发生了什么事情在那里。有没有人有在Hmisc乳胶功能体验?
ctab <- function(tab, dec = 2, margin = NULL) {
tab <- as.table(tab)
ptab <- paste(round(prop.table(tab, margin = margin) * 100, dec), "%", sep = "")
res <- matrix(NA, nrow = nrow(tab) , ncol = ncol(tab) * 2, byrow = TRUE)
oddc <- 1:ncol(tab) %% 2 == 1
evenc <- 1:ncol(tab) %% 2 == 0
res[,oddc ] <- tab
res[,evenc ] <- ptab
res <- as.table(res)
colnames(res) <- rep(colnames(tab), each = 2)
rownames(res) <- rownames(tab)
return(res)
}
我想创建格式化为同时包含对于每个列或变量的计数和百分比乳胶输出的表。我还没有找到一个现成的解决了这个问题,但我觉得必须重新创建轮在一定程度上。
我已经制定了直表格的解决方案,但我有一些采用了交叉表中挣扎。
首先一些示例数据:
#Generate sample data
dow <- sample(1:7, 100, replace=TRUE)
purp <- sample(1:4, 100, replace=TRUE)
dow <- factor(dow, 1:7, c("Mon", "Tues", "Wed", "Thurs", "Fri", "Sat", "Sun"))
purp <- factor(purp, 1:4, c("Business", "Commute", "Vacation", "Other"))
和现在工作直选项卡的功能:
customTable <- function(var, capt = NULL){
counts <- table(var)
percs <- 100 * prop.table(counts)
print(
xtable(
cbind(
Count = counts
, Percent = percs
)
, caption = capt
, digits = c(0,0,2)
)
, caption.placement="top"
)
}
#Usage
customTable(dow, capt="Day of Week")
customTable(purp, capt="Trip Pupose")
没有人有采用这种用于交叉表格(即,由行程目的星期几)的任何建议?以下是我目前写的,不使用xtable库,几乎工作,但不是动态的,是相当丑陋的工作与:
#Create table and percentages
a <- table(dow, purp)
b <- round(prop.table(a, 1),2)
#Column bind all of the counts & percentages together, this SHOULD become dynamic in future
d <- cbind( cbind(Count = a[,1],Percent = b[,1])
, cbind(Count = a[,2], Percent = b[,2])
, cbind(Count = a[,3], Percent = b[,3])
, cbind(Count = a[,4], Percent = b[,4])
)
#Ugly function that needs help, or scrapped for something else
crossTab <- function(title){
cat("\\begin{table}[ht]\n")
cat("\\begin{center}\n")
cat("\\caption{", title, "}\n", sep="")
cat("\\begin{tabular}{rllllllll}\n")
cat("\\hline\n")
cat("", cat("", paste("&\\multicolumn{2}{c}{",colnames(a), "}"), sep = ""), "\\\\\n", sep="")
c("&", cat("", colnames(d), "\\\\\n", sep=" & "))
cat("\\hline\n")
c("&", write.table(d, sep = " & ", eol="\\\\\n", quote=FALSE, col.names=FALSE))
cat("\\hline\n")
cat("\\end{tabular}\n")
cat("\\end{center}\n")
cat("\\end{table}\n")
}
crossTab(title = "Day of week BY Trip Purpose")
解决方案 3
我无法弄清楚如何使用xtable生成一个多列标题,但我没有意识到我会串连我的计数和百分比为同一列印刷目的。不理想,但似乎把工作做好。下面是我写的函数:
ctab3 <- function(row, col, margin = 1, dec = 2, percs = FALSE, total = FALSE, tex = FALSE, caption = NULL){
tab <- as.table(table(row,col))
ptab <- signif(prop.table(tab, margin = margin), dec)
if (percs){
z <- matrix(NA, nrow = nrow(tab), ncol = ncol(tab), byrow = TRUE)
for (i in 1:ncol(tab)) z[,i] <- paste(tab[,i], ptab[,i], sep = " ")
rownames(z) <- rownames(tab)
colnames(z) <- colnames(tab)
if (margin == 1 & total){
rowTot <- paste(apply(tab, 1, sum), apply(ptab, 1, sum), sep = " ")
z <- cbind(z, Total = rowTot)
} else if (margin == 2 & total) {
colTot <- paste(apply(tab, 2, sum), apply(ptab, 2, sum), sep = " ")
z <- rbind(z,Total = colTot)
}
} else {
z <- table(row, col)
}
ifelse(tex, return(xtable(z, caption)), return(z))
}
可能不是最终产品,但确实允许在参数的一些灵活性。在最基本的层面上,只是table()
的包装,但也能产生LaTeX的格式化输出为好。以下是我结束了使用Sweave
文件中:
<<echo = FALSE>>=
for (i in 1:ncol(df)){
print(ctab3(
col = df[,1]
, row = df[,i]
, margin = 2
, total = TRUE
, tex = TRUE
, caption = paste("Dow by", colnames(df[i]), sep = " ")
))
}
@
其他提示
在表中,包是一个行:
# data:
dow <- sample(1:7, 100, replace=TRUE)
purp <- sample(1:4, 100, replace=TRUE)
dow <- factor(dow, 1:7, c("Mon", "Tues", "Wed", "Thurs", "Fri", "Sat", "Sun"))
purp <- factor(purp, 1:4, c("Business", "Commute", "Vacation", "Other"))
dataframe <- data.frame( dow, purp)
# The packages
library(tables)
library(Hmisc)
# The table
tabular( (Weekday=dow) ~ (Purpose=purp)*(Percent("row")+ 1) ,data=dataframe )
# The latex table
latex( tabular( (Weekday=dow) ~ (Purpose=purp)*(Percent("col")+ 1) ,data=dataframe ))
使用booktabs,将得到这个(可进一步定制):
大的问题,这一个困扰了我一段时间(它不是的是的努力,这只是我懒惰的地狱......像往常一样)。但是...虽然这个问题的伟大,你的方法,我很害怕,是不是。有无价的包叫做xtable
,你可以(MIS)使用。此外,这个问题太常见 - 有一个很大的机会,已经有一些现成的解决方案坐在某处的的因特网和的。
这些天,我要工作了一劳永逸(我会发布在GitHub上的代码)。其主要思想去有点像这样:你愿意和相继绝对和相对频率(或%)一个小区(由\分隔)或行内的频率和/或百分比值?我会用2 第二一个去,所以我现在就张贴了“急救”的解决方案:
ctab <- function(tab, dec = 2, ...) {
tab <- as.table(tab)
ptab <- paste(round(prop.table(tab) * 100, dec), "%", sep = "")
res <- matrix(NA, nrow = nrow(tab) * 2, ncol = ncol(tab), byrow = TRUE)
oddr <- 1:nrow(tab) %% 2 == 1
evenr <- 1:nrow(tab) %% 2 == 0
res[oddr, ] <- tab
res[evenr, ] <- ptab
res <- as.table(res)
colnames(res) <- colnames(tab)
rownames(res) <- rep(rownames(tab), each = 2)
return(res)
}
现在你可以试试:
data(HairEyeColor) # load an appropriate dataset
tb <- HairEyeColor[, , 1] # choose only male respondents
ctab(tb)
Brown Blue Hazel Green
Black 32 11 10 3
Black 11.47% 3.94% 3.58% 1.08%
Brown 53 50 25 15
Brown 19% 17.92% 8.96% 5.38%
Red 10 10 7 7
Red 3.58% 3.58% 2.51% 2.51%
Blond 3 30 5 8
Blond 1.08% 10.75% 1.79% 2.87%
请确保您加载xtable
包装和使用print
(这是一个通用的功能,所以你必须通过一个xtable
归类对象)。您禁止行名字是很重要的。我会优化这一个明天 - 它应该是xtable
兼容。这是凌晨3点在我的时区,所以这些线路我将结束我的回答:
print(xtable(ctab(tb)), include.rownames = FALSE)
干杯!
使用multicolumn
与来自在 Hmisc 强>包latex
不会太差。这种最小Sweave文件:
\documentclass{article}
\begin{document}
<<echo = FALSE,results = tex>>=
library(Hmisc)
dow <- sample(1:7, 100, replace=TRUE)
purp <- sample(1:4, 100, replace=TRUE)
dow <- factor(dow, 1:7, c("Mon", "Tues", "Wed", "Thurs", "Fri", "Sat", "Sun"))
purp <- factor(purp, 1:4, c("Business", "Commute", "Vacation", "Other"))
tbl <- table(dow,purp)
tbl_prop <- round(100 * prop.table(tbl,1),2)
tbl_df <- as.data.frame.matrix(tbl)
tbl_prop_df <- as.data.frame.matrix(tbl_prop)
colnames(tbl_prop_df) <- paste(colnames(tbl_prop_df),"1",sep = "")
df <- cbind(tbl_df,tbl_prop_df)[,ggplot2:::interleave(1:4,5:8)]
colnames(df) <- rep(c('n','\\%'),times = 4)
latex(object=df,file="",cgroup = colnames(tbl_df),
colheads = NULL,rowlabel = "",
center = "centering",collabel.just = rep("r",8))
@
\end{document}
产生以下对我来说:
显然,我已经硬编码的东西公平一点,有可能是滑头的方式来生产,你最终传递到latex
数据帧,但这应该使用multicolum
至少要给一个开始。
此外,轻微的疑难杂症,我使用的 GGPLOT2 强>组合计数和百分比时的interleave
函数交替的列。这只是因为我懒。
如何将这项工作的吗?
library(reshape)
library(plyr)
df <- data.frame(dow = dow, purp = purp)
df.count <- count(df)
df.count <- ddply(df.count, .(dow), transform, p = round(freq / sum(freq),2))
df.m <- melt(df.count)
df.print <- cast(df.m, dow ~ purp + variable)
library(xtable)
xtable(df.print)
它不给你好看multicolumns,我没有与xtable
足够的经验,找出如果可能的话。但是,如果你将要编写自定义的功能,你可以尝试其中一个工作在df.print
的列名。你可能甚至能够写入一个足够一般采取重铸数据帧作为输入的所有的方式。
修改强>
只是想到了一个很好的解决方案来让你更接近。创建df.m
后
df.preprint <- ddply(df.m, .(dow, purp), function(x){
x <- cast(x, dow ~ variable)
x$value <- paste(x$freq, x$p, sep = " / ")
return(c(value = x$value))
}
)
df.print <- cast(df.preprint, dow ~ purp)
print(xtable(df.print), include.rownames = F)
现在,每一个细胞将包含N / percent
值
我意识到这个线程是有点老了,但在reporttools包tableNominal()函数可以提供你正在寻找的功能。
tab<-table(row, col)
ctab<-round(100*prop.table(tab,2), 2) # for column percents (see the args for prop.table)
for (i in 1:length(tab)) {
ctab[i]<-paste(tab[i]," (", ctab[i], "%", ")", sep="")
}
require(xtable);
k<-xtable(ctab,digits=1) # make latex table