【问题标题】:Summarise and list custom index in dplyr总结并列出 dplyr 中的自定义索引
【发布时间】:2017-12-25 00:37:13
【问题描述】:

我正在尝试输出分组汇总变量以及相应的识别变量列表。

dplyr::starwars 数据集为例,我想计算具有“浅”肤色的字符数,按性别分组,并在单独的输出列中使用与每个匹配项对应的名称向量。

在实际用例中,summarise 的条件不止一种,唯一标识符可能是subjectID/studyID/等。我对data.table 解决方案持开放态度,更喜欢基于矢量、R Shiny 友好、易于转换为函数的解决方案。

来自dplyr::starwars的示例:

starwars %>% 
  filter(species %in% c("Human", "Droid")) %>%
  group_by(gender) %>%
  summarise(
    skin = sum(skin_color=="light", na.rm=T),
    hair = sum(hair_color=="brown", na.rm=T)
  )

期望的输出:

gender skin hair  skinname                                                   hairname
 female  6   6  femname1, femname2, femname3, femname4, femname5, femname6   femhname1, femhname2, femhname3, femhname4, femhname5, femhname6
 male    5   8  mname1, mname2, mname3, mname4, mname5                       mhname1, mhname2, mhname3, mhname4, mhname5, mhname6, mhname7 mhname8
 none    0   0                                                 
 <NA>    0   0  

然后,此输出将使用t() 转置,并使用paste()DT(数据表)中创建匹配名称的悬停显示。

我想我需要类似的东西

skinname = as.list(.$name[which(skin_color == "light")])

summarise 步骤中,或者可能是在summarise/mutate 中带有do.call 的自定义函数。

【问题讨论】:

    标签: r dplyr summarize


    【解决方案1】:

    如果你想要一个嵌套的data.frame,你可以使用tidyr::nest:

    library(tidyverse)
    
    starwars %>%
        filter(species %in% c("Human", "Droid"), 
               skin_color == 'light') %>%
        group_by(gender) %>% 
        group_by(skin = n(), add = TRUE) %>% 
        nest(name)
    #> # A tibble: 2 x 3
    #>   gender  skin             data
    #>    <chr> <int>           <list>
    #> 1 female     6 <tibble [6 x 1]>
    #> 2   male     5 <tibble [5 x 1]>
    

    或者如果您只想要嵌套向量,请使用list 进行总结:

    starwars %>%
        filter(species %in% c("Human", "Droid"), 
               skin_color == 'light') %>%
        group_by(gender) %>% 
        summarise(skin = n(),
                  name = list(name))
    #> # A tibble: 2 x 3
    #>   gender  skin      name
    #>    <chr> <int>    <list>
    #> 1 female     6 <chr [6]>
    #> 2   male     5 <chr [5]>
    

    或者如果你想保留空行,子集而不是过滤器:

    starwars %>% 
        filter(species %in% c("Human", "Droid")) %>%
        group_by(gender) %>%
        summarise(
            skin = sum(skin_color == "light"), 
            name = list(name[skin_color == 'light'])
        )
    #> # A tibble: 4 x 3
    #>   gender  skin      name
    #>    <chr> <int>    <list>
    #> 1 female     6 <chr [6]>
    #> 2   male     5 <chr [5]>
    #> 3   none     0 <chr [0]>
    #> 4   <NA>     0 <chr [0]>
    

    如果您想将名称折叠为单个字符串,toString 可以完成这项工作,但如果您打算稍后分开,请确保字符串中没有逗号。

    【讨论】:

    • 感谢您,我应该提到目标是创建一个包含多个条件计数的分组汇总表。因此,我认为将skin_color == light 移动到filter() 步骤将不起作用。我将编辑问题以澄清。
    • 那么听起来你应该分组而不是过滤。
    • 我相信您的最后一个选择就是我正在寻找的解决方案,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 2014-03-05
    相关资源
    最近更新 更多