我遇到了这样的数据:
df <- data.frame(id = 1:1000,
x = sample(0:30, 1000, replace = T),
y = sample(50:10000, 1000, replace = T))
我想基于多个条件(即
)分配另一个名为z
的列
if x <= 5 & y <= 100, z = 1
if x > 5 & x <= 10 & y <= 100, z = 2
if x > 10 & x <= 12 & y <= 100, z = 3
if x > 12 & x <= 20 & y <= 100, z = 4
if x > 20 & x <= 30 & y <= 100, z = 5
if x <= 5 & y > 100 & y <= 1000, z = 6
if x > 5 & x <= 10 & y > 100 & y <= 1000 z = 7
if x > 10 & x <= 12 & y > 100 & y <= 1000, z = 8
if x > 12 & x <= 20 & y > 100 & y <= 1000, z = 9
if x > 20 & x <= 30 & y > 100 & y <= 1000, z = 10
.
.
.
and so. I hope you get the drift.
对我来说,显而易见的解决方案是写一个长ifelse
这样的语句;
df %>% mutate(z = ifelse(x <= 5 & y <= 100, 1,
ifelse(x > 5 & x <= 10 & y <= 100, 2,
ifelse(x > 10 & x <= 12 & y <= 100, 3))),
........... and son on)
您会发现这样的脚本可能无休止地长,我想知道是否还有其他方法可以在不编写长ifelse
语句的情况下实现这一目标。
答案 0 :(得分:5)
如果if else语句中有一个模式,我们可以预先创建一组表达式,并使用!!!
取消qoute并将它们拼接为case_when
的参数:
x_gt_cond <- rep(c(-Inf, 5, 10, 12, 20), 2)
x_le_cond <- rep(c(5, 10, 12, 20 ,30), 2)
y_gt_cond <- rep(c(-Inf, 100), each = 5)
y_le_cond <- rep(c(100, 1000), each = 5)
z <- 1:10
cases <- paste("x > ", x_gt_cond, "& x <= ", x_le_cond,
"& y > ", y_gt_cond, "& y <= ", y_le_cond, "~ ", z)
library(dplyr)
library(rlang)
df %>%
mutate(z = case_when(!!!parse_exprs(cases)))
诀窍是使用-Inf
和Inf
作为下限和上限,以便使x
和y
具有平衡的条件。此解决方案的优雅之处在于,您只需更改_cond
向量即可添加更多条件。
输出:
> cases
[1] "x > -Inf & x <= 5 & y > -Inf & y <= 100 ~ 1"
[2] "x > 5 & x <= 10 & y > -Inf & y <= 100 ~ 2"
[3] "x > 10 & x <= 12 & y > -Inf & y <= 100 ~ 3"
[4] "x > 12 & x <= 20 & y > -Inf & y <= 100 ~ 4"
[5] "x > 20 & x <= 30 & y > -Inf & y <= 100 ~ 5"
[6] "x > -Inf & x <= 5 & y > 100 & y <= 1000 ~ 6"
[7] "x > 5 & x <= 10 & y > 100 & y <= 1000 ~ 7"
[8] "x > 10 & x <= 12 & y > 100 & y <= 1000 ~ 8"
[9] "x > 12 & x <= 20 & y > 100 & y <= 1000 ~ 9"
[10] "x > 20 & x <= 30 & y > 100 & y <= 1000 ~ 10"
id x y z
1 1 13 8440 NA
2 2 3 1467 NA
3 3 5 2699 NA
4 4 24 5286 NA
5 5 5 2378 NA
6 6 16 268 9
7 7 19 2910 NA
8 8 19 706 9
9 9 24 6212 NA
10 10 7 6026 NA
...
答案 1 :(得分:2)
您似乎正在寻找case_when
中的dplyr
函数。就您而言,它可能看起来像这样。
df %>% mutate(z = case_when(
x <= 5 & y <= 100 ~ 1,
x > 5 & x <= 10 & y <= 100 ~ 2,
x > 10 & x <=12 & y <= 100 ~ 3
)
)
edit:更改了答案以反映case_when
在dplyr
包中。感谢您在下面的评论。