首页 文章

使用dplyr创建包含多个分类/因子变量的汇总比例表

提问于
浏览
9

我正在尝试创建一个表,用另一个变量汇总几个分类变量(使用频率和比例) . 我想使用dplyr包来做到这一点 .

以前的Stack Overflow讨论部分涉及我正在寻找的内容:Relative frequencies / proportions with dplyrCalculate relative frequency for a certain group .

使用mtcars数据集,如果我只是想查看 gear by 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 amcyl by am ,分别在同一个表中 . 如果我将代码修改为:

mtcars %>%
    group_by (am, gear, carb, cyl) %>%
    summarise (n = n()) %>%
    mutate(freq = n / sum(n))

我得到了 amgearcarbcyl 的每个组合的频率 . 这不是我想要的 . 有没有办法用dplyr做到这一点?

EDIT

此外,如果有人知道生成我想要的表的方法,但是 am 的类别作为列(如经典的2x2表格式),这将是一个额外的好处 . 这是我所指的一个例子 . 它来自我之前的一篇出版物 . 我想在R中生成这个表,这样我就可以使用RMarkdown将它直接输出到word文档:

enter image description here

2 回答

  • 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))
    
  • 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%)
    

相关问题