【发布时间】:2021-02-16 10:01:07
【问题描述】:
当我们想根据一个条件改变几个新列时,有没有办法避免重复代码?
例如,在mtcars 数据集中,我想创建两个新列。一列将分类汽车是否“经济”,另一列将描述每辆车获得的“标签”的颜色。
library(dplyr)
mtcars %>%
select(mpg, am) %>%
mutate(economic = case_when(mpg <= 17 & am == 0 ~ "no",
mpg > 17 & am == 1 ~ "yes"),
label = case_when(mpg <= 17 & am == 0 ~ "red",
mpg > 17 & am == 1 ~ "green"))
#> mpg am economic label
#> Mazda RX4 21.0 1 yes green
#> Mazda RX4 Wag 21.0 1 yes green
#> Datsun 710 22.8 1 yes green
#> Hornet 4 Drive 21.4 0 <NA> <NA>
#> Hornet Sportabout 18.7 0 <NA> <NA>
#> Valiant 18.1 0 <NA> <NA>
#> Duster 360 14.3 0 no red
#> Merc 240D 24.4 0 <NA> <NA>
#> Merc 230 22.8 0 <NA> <NA>
#> Merc 280 19.2 0 <NA> <NA>
#> Merc 280C 17.8 0 <NA> <NA>
#> Merc 450SE 16.4 0 no red
#> Merc 450SL 17.3 0 <NA> <NA>
#> Merc 450SLC 15.2 0 no red
#> Cadillac Fleetwood 10.4 0 no red
#> Lincoln Continental 10.4 0 no red
#> Chrysler Imperial 14.7 0 no red
#> Fiat 128 32.4 1 yes green
#> Honda Civic 30.4 1 yes green
#> Toyota Corolla 33.9 1 yes green
#> Toyota Corona 21.5 0 <NA> <NA>
#> Dodge Challenger 15.5 0 no red
#> AMC Javelin 15.2 0 no red
#> Camaro Z28 13.3 0 no red
#> Pontiac Firebird 19.2 0 <NA> <NA>
#> Fiat X1-9 27.3 1 yes green
#> Porsche 914-2 26.0 1 yes green
#> Lotus Europa 30.4 1 yes green
#> Ford Pantera L 15.8 1 <NA> <NA>
#> Ferrari Dino 19.7 1 yes green
#> Maserati Bora 15.0 1 <NA> <NA>
#> Volvo 142E 21.4 1 yes green
由reprex package (v0.3.0) 于 2021-02-16 创建
在上面的代码中,我必须两次指定相同的条件,每个新列一个。
- IF
mpg <= 17 & am == 0THEN 赋值 X - IF
mpg > 17 & am == 1THEN 赋值 Y
我是否可以使用这组条件来改变几个新列,以便每列都有自己的 X 和 Y 值?
在我的实际数据中,我经常遇到复杂的条件,这些条件会导致许多新列发生变异,而且我发现自己一遍又一遍地重复相同的代码来处理条件。有没有办法将条件勾勒一次,然后根据同一组条件创建多个列?
编辑 1
我想知道——尽管它不会完全解决上述问题——是否有办法将条件存储到对象中并在以后解包?比如:
cond_1 <- {mpg <= 17 & am == 0}
cond_2 <- {mpg > 17 & am == 1}
mtcars %>%
select(mpg, am) %>%
mutate(economic = case_when(cond_1 ~ "no",
cond_2 ~ "yes"),
label = case_when(cond_1 ~ "red",
cond_2 ~ "green"))
至少会让代码更简洁...
编辑 2
基于this solution,我学会了如何回答我在EDIT 1中提出的问题:
library(dplyr)
library(rlang)
cond_1 <- parse_expr("mpg <= 17 & am == 0")
cond_2 <- parse_expr("mpg > 17 & am == 1")
mtcars %>%
select(mpg, am) %>%
mutate(economic = case_when(!!cond_1 ~ "no",
!!cond_2 ~ "yes"),
label = case_when(!!cond_1 ~ "red",
!!cond_2 ~ "green"))
#> mpg am economic label
#> Mazda RX4 21.0 1 yes green
#> Mazda RX4 Wag 21.0 1 yes green
#> Datsun 710 22.8 1 yes green
#> Hornet 4 Drive 21.4 0 <NA> <NA>
#> Hornet Sportabout 18.7 0 <NA> <NA>
#> Valiant 18.1 0 <NA> <NA>
#> Duster 360 14.3 0 no red
#> Merc 240D 24.4 0 <NA> <NA>
#> Merc 230 22.8 0 <NA> <NA>
#> Merc 280 19.2 0 <NA> <NA>
#> Merc 280C 17.8 0 <NA> <NA>
#> Merc 450SE 16.4 0 no red
#> Merc 450SL 17.3 0 <NA> <NA>
#> Merc 450SLC 15.2 0 no red
#> Cadillac Fleetwood 10.4 0 no red
#> Lincoln Continental 10.4 0 no red
#> Chrysler Imperial 14.7 0 no red
#> Fiat 128 32.4 1 yes green
#> Honda Civic 30.4 1 yes green
#> Toyota Corolla 33.9 1 yes green
#> Toyota Corona 21.5 0 <NA> <NA>
#> Dodge Challenger 15.5 0 no red
#> AMC Javelin 15.2 0 no red
#> Camaro Z28 13.3 0 no red
#> Pontiac Firebird 19.2 0 <NA> <NA>
#> Fiat X1-9 27.3 1 yes green
#> Porsche 914-2 26.0 1 yes green
#> Lotus Europa 30.4 1 yes green
#> Ford Pantera L 15.8 1 <NA> <NA>
#> Ferrari Dino 19.7 1 yes green
#> Maserati Bora 15.0 1 <NA> <NA>
#> Volvo 142E 21.4 1 yes green
由reprex package (v0.3.0) 于 2021 年 2 月 16 日创建
但是,这只会使代码更易于阅读。但是这篇文章的主要问题——条件句的重复——仍然存在。
【问题讨论】:
-
那么在这个修改后的场景中,你的问题到底是什么?
-
我需要多次重复相同的条件。这是一个玩具示例,但想象一下这样一种情况:不仅要创建
economic和label列,而且还有 10 个基于同一组条件的新列。我不想重复代码 10 次。