我正在尝试创建一个表,用另一个变量汇总几个分类变量(使用频率和比例).我想使用dplyr包来做到这一点.
之前的Stack Overflow讨论部分涉及我正在寻找的内容: 使用dplyr的相对频率/比例和计算某个组的相对频率.
使用mtcars数据集,如果我只想查看gear
按am
类别的比例,这就是输出的样子:
mtcars %>% group_by(am, gear) %>% summarise (n = n()) %>% mutate(freq = n / sum(n)) # am gear n freq # 1 0 3 15 0.7894737 # 2 0 4 4 0.2105263 # 3 1 4 8 0.6153846 # 4 1 5 5 0.3846154
但是,我实际上不仅要在同一个表中查看gears
by am
,还要分别查看carb
by am
和cyl
by am
.如果我将代码修改为:
mtcars %>% group_by (am, gear, carb, cyl) %>% summarise (n = n()) %>% mutate(freq = n / sum(n))
我得到的频率的每个组合am
,gear
,carb
,和cyl
.这不是我想要的.有没有办法用dplyr做到这一点?
编辑
此外,如果有人知道生成我想要的表的方法,但是am
作为列的类别(如经典的2x2表格式),这将是一个额外的好处.这是我所指的一个例子.它来自我之前的一篇出版物.我想在R中生成这个表,这样我就可以使用RMarkdown将它直接输出到word文档:
解决此问题的一种方法是将数据转换为长(呃)格式.然后,您可以使用相同的代码来计算您想要的结果,并使用一个额外的group_by:
library(reshape2) library(dplyr) m_mtcars <- melt(mtcars,measure.vars=c("gear","carb","cyl")) res <- m_mtcars %>% group_by(am, variable, value) %>% summarise (n = n()) %>% mutate(freq = n / sum(n))
在此基础上,可以使用更多重新整形和一些字符串格式化来获得所需的输出
#make an 'export' variable res$export <- with(res, sprintf("%i (%.1f%%)", n, freq*100)) #reshape again output <- dcast(variable+value~am, value.var="export", data=res, fill="missing") #use drop=F to prevent silent missings #'silent missings' output$variable <- as.character(output$variable) #make 'empty lines' empties <- data.frame(variable=unique(output$variable), stringsAsFactors=F) empties[,colnames(output)[-1]] <- "" #bind them together output2 <- rbind(empties,output) output2 <- output2[order(output2$variable,output2$value),] #optional: 'remove' variable if value present output2$variable[output2$value!=""] <- ""
这导致:
variable value 0 1 2 carb 7 1 3 (15.8%) 4 (30.8%) 8 2 6 (31.6%) 4 (30.8%) 9 3 3 (15.8%) missing 10 4 7 (36.8%) 3 (23.1%) 11 6 missing 1 (7.7%) 12 8 missing 1 (7.7%) 3 cyl 13 4 3 (15.8%) 8 (61.5%) 14 6 4 (21.1%) 3 (23.1%) 15 8 12 (63.2%) 2 (15.4%) 1 gear 4 3 15 (78.9%) missing 5 4 4 (21.1%) 8 (61.5%) 6 5 missing 5 (38.5%)
使用tidyr/dplyr组合,您可以这样做:
library(tidyr) library(dplyr) mtcars %>% gather(variable, value, gear, carb, cyl) %>% group_by(am, variable, value) %>% summarise (n = n()) %>% mutate(freq = n / sum(n))