我正在尝试创建一个表,用另一个变量汇总几个分类变量(使用频率和比例)。我想使用dplyr包来做到这一点。
以前的Stack Overflow讨论部分是我正在寻找的: Relative frequencies / proportions with dplyr和Calculate relative frequency for a certain group。
使用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
am
,carb
am
和cyl
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文档:
答案 0 :(得分:8)
解决此问题的一种方法是将数据转换为长(呃)格式。然后,您可以使用相同的代码来计算您想要的结果,并使用一个额外的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%)
答案 1 :(得分: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))
答案 2 :(得分:-1)
分组然后汇总的另一种方法是使用count()。
这只会使代码1行更简洁
library(reshape2)
library(dplyr)
m_mtcars <- melt(mtcars,measure.vars=c("gear","carb","cyl"))
res <- m_mtcars %>%
count(am, variable, value) %>%
mutate(freq = n / sum(n))
另一个好处是,这将保存在group_by摘要中丢失的其他值。结果表如下所示