根据 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
我会简单地使用 cut
和 seq
:
定义的中断
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
如果需要测试范围,可以使用 pmin
和 pmax
。
(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
我有以下数据集
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我会简单地使用 cut
和 seq
:
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
如果需要测试范围,可以使用 pmin
和 pmax
。
(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