使用dplyr有条件地更新多个变量

问题描述:

我正在尝试使用单个条件语句使用dplyr更新R中的多个变量。我有一些工作代码(在下面发布),但是我觉得它效率很低,并且确信必须有更好的方法来做到这一点。

I am trying to use a single conditional statement to update multiple variables in R using dplyr. I have some working code (posted below) however I feel it is very inefficient and am convinced there must be a better way of doing it.

编辑:程序目的的文字描述。这个想法是使虹膜数据集根据Species的值更新多个变量,例如,如果Species == setosa则Species = SETOSA,Sepal.Length * = 1.5,Sepal.Width * = 0.5。

Worded description of purpose of the program. The idea is to take the iris dataset an update multiple variables based upon the value of Species, for example if Species == "setosa" then Species = "SETOSA" , Sepal.Length *= 1.5 , Sepal.Width *= 0.5.

library(dplyr)
library(tibble)

multi_update <- function(species , sepal.length , sepal.width , ret){

  if ( species == "setosa")  {
    RET <- list( 
      Species      = "SETOSA",
      Sepal.Length = sepal.length * 1.5,
      Sepal.Width  = sepal.width * 0.5
    )
  } else if ( species == "versicolor") {
    RET <- list( 
      Species      = "VERSI",
      Sepal.Length = sepal.length * 2,
      Sepal.Width  = sepal.width * 1.5
    )
  } else {
    RET <- list( 
      Species      = species,
      Sepal.Length = sepal.length ,
      Sepal.Width  = sepal.width 
    )
  }                     
  return( RET[[ret]] )
}

iris %>% 
  tbl_df %>% 
  mutate( Sepal.Length = mapply(multi_update , Species , Sepal.Length , Sepal.Width , "Sepal.Length")) %>% 
  mutate( Sepal.Width  = mapply(multi_update , Species , Sepal.Length , Sepal.Width , "Sepal.Width")) %>% 
  mutate( Species      = mapply(multi_update , Species , Sepal.Length , Sepal.Width , "Species"))


我们可以创建键值数据集与原始数据集连接,并对列进行变异

We can create a key val dataset, join with the original dataset and mutate the columns

library(dplyr)
kval <- data.frame(Species = c("setosa", "versicolor", "virginica"),
       Species.x = c("SETOSA", "VERSI", "virginica"), 
      Sepal.Length = c(1.5, 2, 1), Sepal.Width = c(0.5, 1.5, 1))
res <- left_join(iris, kval, by = "Species") %>% 
           mutate(Species = Species.x, Sepal.Length = Sepal.Length.x*Sepal.Length.y, 
             Sepal.Width = Sepal.Width.x * Sepal.Width.y) %>%
            select(-matches("(.x|.y)$"))
head(res)
#  Petal.Length Petal.Width Species Sepal.Length Sepal.Width
#1          1.4         0.2  SETOSA         7.65        1.75
#2          1.4         0.2  SETOSA         7.35        1.50
#3          1.3         0.2  SETOSA         7.05        1.60
#4          1.5         0.2  SETOSA         6.90        1.55
#5          1.4         0.2  SETOSA         7.50        1.80
#6          1.7         0.4  SETOSA         8.10        1.95