group_by()
是最重要的分组动词,需要一个数据框和一个或多个变量进行分组:
详情: https://cloud.r-project.org/web/packages/dplyr/vignettes/grouping.html
我们首先加载 dplyr:
library(dplyr)
添加分组 group_by()
最重要的分组动词是group_by()
:它需要一个数据框和一个或多个变量进行分组:
by_species <- starwars %>% group_by(species)
by_sex_gender <- starwars %>% group_by(sex, gender)
在添加分组后,print()打印时可以看到分组:
by_species
#> # A tibble: 87 x 14
#> # Groups: species [38]
#> name height mass hair_color skin_color eye_color birth_year sex gender
#> <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
#> 1 Luke Sk~ 172 77 blond fair blue 19 male mascu~
#> 2 C-3PO 167 75 <NA> gold yellow 112 none mascu~
#> 3 R2-D2 96 32 <NA> white, bl~ red 33 none mascu~
#> 4 Darth V~ 202 136 none white yellow 41.9 male mascu~
#> 5 Leia Or~ 150 49 brown light brown 19 fema~ femin~
#> 6 Owen La~ 178 120 brown, grey light blue 52 male mascu~
#> # ... with 81 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#> # films <list>, vehicles <list>, starships <list>
计算每个分组的行数,可以通过
sort
参数控制排序方式。
by_species %>% tally()
#> # A tibble: 38 x 2
#> species n
#> <chr> <int>
#> 1 Aleena 1
#> 2 Besalisk 1
#> 3 Cerean 1
#> 4 Chagrian 1
#> 5 Clawdite 1
#> 6 Droid 6
#> # ... with 32 more rows
by_sex_gender %>% tally(sort = TRUE)
#> # A tibble: 6 x 3
#> # Groups: sex [5]
#> sex gender n
#> <chr> <chr> <int>
#> 1 male masculine 60
#> 2 female feminine 16
#> 3 none masculine 5
#> 4 <NA> <NA> 4
#> 5 hermaphroditic masculine 1
#> 6 none feminine 1
在数据探索时比较有用。
除了按照现有变量分组外,还可以按照函数处理后的变量分组,等效在mutate()
之后执行group_by
:
bmi_breaks <- c(0, 18.5, 25, 30, Inf)
starwars %>%
group_by(bmi_cat = cut(mass/(height/100)^2, breaks=bmi_breaks)) %>%
tally()
#> # A tibble: 5 x 2
#> bmi_cat n
#> <fct> <int>
#> 1 (0,18.5] 10
#> 2 (18.5,25] 24
#> 3 (25,30] 13
#> 4 (30,Inf] 12
#> 5 <NA> 28
group_by()可通过在group_by()计算产生的新字段分组
查看分组group_keys()
使用group_keys()
查看数据的分组,每个组一行,每个分组变量占一列:
by_species %>% group_keys() #> # A tibble: 38 x 1 #> species #> <chr> #> 1 Aleena #> 2 Besalisk #> 3 Cerean #> 4 Chagrian #> 5 Clawdite #> 6 Droid #> # ... with 32 more rows
by_sex_gender %>% group_keys()
#> # A tibble: 6 x 2
#> sex gender
#> <chr> <chr>
#> 1 female feminine
#> 2 hermaphroditic masculine
#> 3 male masculine
#> 4 none feminine
#> 5 none masculine
#> 6 <NA> <NA>
也可以使用命令group_indices()
查看每行属于哪个组:
by_species %>% group_indices()
#> [1] 11 6 6 11 11 11 11 6 11 11 11 11 34 11 24 12 11 11 36 11 11 6 31 11 11
#> [26] 18 11 11 8 26 11 21 11 10 10 10 38 30 7 38 11 37 32 32 33 35 29 11 3 20
#> [51] 37 27 13 23 16 4 11 11 11 9 17 17 11 11 11 11 5 2 15 15 11 1 6 25 19
#> [76] 28 14 34 11 38 22 11 11 11 6 38 11
该特性方便增加组别列。
df <- tibble(a = c('a','a','a','b','b','b','d','e','f'))
df %>%
group_by(a) %>%
mutate(组别列 = group_indices() )
#> Warning: `group_indices()` was deprecated in dplyr 1.0.0.
#> Please use `cur_group_id()` instead.
#> # A tibble: 9 x 2
#> # Groups: a [5]
#> a 组别列
#> <chr> <int>
#> 1 a 1
#> 2 a 1
#> 3 a 1
#> 4 b 2
#> 5 b 2
#> 6 b 2
#> # ... with 3 more rows
上述用法在dplyr 1.0.0 中弃用,用cur_group_id()
代替,如下所示
df %>%
group_by(a) %>%
mutate(组别列 = cur_group_id())
#> # A tibble: 9 x 2
#> # Groups: a [5]
#> a 组别列
#> <chr> <int>
#> 1 a 1
#> 2 a 1
#> 3 a 1
#> 4 b 2
#> 5 b 2
#> 6 b 2
#> # ... with 3 more rows
dplyr 在我看来 API 变化较快,所以我个人习惯使用 data.table 包处理数据。所以在学习的时候用最新的版本学习。
group_rows()
每个组包含哪些行:
by_species %>% group_rows() %>% head()
#> <list_of<integer>[6]>
#> [[1]]
#> [1] 72
#>
#> [[2]]
#> [1] 68
#>
#> [[3]]
#> [1] 49
#>
#> [[4]]
#> [1] 56
#>
#> [[5]]
#> [1] 67
#>
#> [[6]]
#> [1] 2 3 8 22 73 85
group_vars()
返回分组变量的名称,请使用:
by_species %>% group_vars() #> [1] "species"
by_sex_gender %>% group_vars()
#> [1] "sex" "gender"
删除分组变量ungroup()
要删除所有分组变量,使用ungroup()
:
by_species %>%
ungroup() %>%
tally()
#> # A tibble: 1 x 1
#> n
#> <int>
#> 1 87
还可以通过列出要删除的变量来有选择的删除分组变量:
by_sex_gender %>%
ungroup(sex) %>%
tally()
#> # A tibble: 3 x 2
#> gender n
#> <chr> <int>
#> 1 feminine 17
#> 2 masculine 66
#> 3 <NA> 4