根据相同条件创建多列

时间:2021-02-16 10:01:07

标签: r dplyr

当我们想根据一个条件改变几个新列时,有没有办法避免重复代码?

例如,在 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 年 2 月 16 日创建

在上面的代码中,我必须两次指定相同的条件,每个新列一个。

  • IF mpg <= 17 & am == 0 THEN 赋值 X
  • IF mpg > 17 & am == 1 THEN 赋值 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,我学会了如何回答我在编辑 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 日创建

然而,这只会使代码更易于阅读。但是这篇文章的主要问题——条件的重复——仍然存在。

1 个答案:

答案 0 :(得分:0)

并不是真正的最佳解决方案,但一种方法是使用先前创建的列作为输入来创建新列。这样可以避免一次又一次地编写条件。

=1=INDIRECT("Sheet1!"&CELL("address",A1))