根据 R 中的出生年份对人员进行分组

Group persons based on birth of year in R

我有以下数据集

df<- data.frame(x1=c(1,5,7,8,2,2,3,4,5,10),
birthyear=c(1992,1994,1993,1992,1995,1999,2000,2001,2000, 1994))

我想以 3 年为间隔将人分组在一起,这样 1992-1994 年出生的人属于第 1 组,1995-1997 年出生的人属于第 2 组,依此类推。我有一个更大的数据集,其中包含超过 10000 个条目。我怎样才能最有效地做到这一点?

这是一种相当手动的方法,使用 case_when,您可以在其中为每个组定义年份跨度。使用 case_when 时,您定义一个条件,例如birthyear > 1991 & birthyear < 1995,结果使用波浪号 ~,例如~ 1.

library(dplyr)

df<- data.frame(x1=c(1,5,7,8,2,2,3,4,5,10),
                birthyear=c(1992,1994,1993,1992,1995,1999,2000,2001,2000, 1994))

df %>% 
  mutate(group = case_when(
    birthyear > 1991 & birthyear < 1995 ~ 1,
    birthyear > 1994 & birthyear < 1997 ~ 2,
    birthyear > 1997 & birthyear < 2002 ~ 3
  ))

#>    x1 birthyear group
#> 1   1      1992     1
#> 2   5      1994     1
#> 3   7      1993     1
#> 4   8      1992     1
#> 5   2      1995     2
#> 6   2      1999     3
#> 7   3      2000     3
#> 8   4      2001     3
#> 9   5      2000     3
#> 10 10      1994     1

reprex package (v0.3.0)

创建于 2022-05-03

我会简单地使用 cutseq:

定义的中断
df$group <- cut(df$birthyear,
                seq(1992, 2022, 3),
                labels = F,
                right = F)
df

输出:

#>    x1 birthyear group
#> 1   1      1992     1
#> 2   5      1994     1
#> 3   7      1993     1
#> 4   8      1992     1
#> 5   2      1995     2
#> 6   2      1999     3
#> 7   3      2000     3
#> 8   4      2001     4
#> 9   5      2000     3
#> 10 10      1994     1

reprex package (v2.0.1)

于 2022-05-03 创建

使用整数除法 %/% 可能是一种有效的方法。

df$group <- (df$birthyear - 1989L) %/% 3L
df
#   x1 birthyear group
#1   1      1992     1
#2   5      1994     1
#3   7      1993     1
#4   8      1992     1
#5   2      1995     2
#6   2      1999     3
#7   3      2000     3
#8   4      2001     4
#9   5      2000     3
#10 10      1994     1

从最低的生日开始:

(df$birthyear - min(df$birthyear) + 3L) %/% 3L
# [1] 1 1 1 1 2 3 3 4 3 1

如果需要测试范围,可以使用 pminpmax

(pmax(1989L, pmin(2023L, df$birthyear)) - 1989L) %/% 3L
# [1] 1 1 1 1 2 3 3 4 3 1

也可以使用findInterval

findInterval(df$birthyear, seq(1992, 2022, 3))
# [1] 1 1 1 1 2 3 3 4 3 1

基准:

set.seed(42)
x <- sample(1992:2021, 10001, TRUE)
bench::mark(
         "cut" = cut(x, seq(1992, 2022, 3), labels = F, right = F),
         "findInterval" = findInterval(x, seq(1992, 2022, 3)),
         "%/%pminMax" = (pmax(1989L, pmin(2023L, x)) - 1989L) %/% 3L,
         "%/%min" = (x - min(x) + 3L) %/% 3L,
         "%/%" = (x - 1989L) %/% 3L
         )
#  expression        min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#  <bch:expr>   <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
#1 cut             219µs  223.9µs     3875.   117.3KB     8.17  1898     4
#2 findInterval  143.2µs  148.9µs     6450.   117.3KB    13.6   2855     6
#3 %/%pminMax     75.2µs   77.7µs    12263.   117.4KB    27.3   5835    13
#4 %/%min         53.7µs   54.1µs    18153.    39.1KB    12.3   8852     6
#5 %/%            35.5µs   35.9µs    27166.    39.1KB    19.0   9993     7