在 dplyr 中汇总并列出自定义索引
Summarise and list custom index in dplyr
我正在尝试输出带有相应标识变量列表的分组摘要变量。
以 dplyr::starwars
数据集为例,我想计算具有 "light" 肤色的字符数,按性别分组,并在一个单独的列表中使用与每个匹配项对应的名称向量输出列。
在实际用例中,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
的自定义函数
如果你想要一个嵌套的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
就可以了,但如果您打算稍后分开,请确保字符串中没有逗号。
我正在尝试输出带有相应标识变量列表的分组摘要变量。
以 dplyr::starwars
数据集为例,我想计算具有 "light" 肤色的字符数,按性别分组,并在一个单独的列表中使用与每个匹配项对应的名称向量输出列。
在实际用例中,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
的自定义函数
如果你想要一个嵌套的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
就可以了,但如果您打算稍后分开,请确保字符串中没有逗号。