R - 在 dplyr::mutate/if_else 组合中寻找更好的语法

标签 r dplyr

我对使用 dplyr::mutate、使用 ifelse/if_else 有条件创建新列有疑问

我将使用 iris 数据集作为示例。首先我定义一个常规设置

setting1 = TRUE; # general setting

我想根据另一个列的值创建一个新列(此处为 Sepal.Length) 但根据 bool 设置1值使用不同的公式。 我的第一步是(按照在某处找到的一些示例,我是 R 的新手):

iris2 <- iris %>% slice_head(n=5) %>%
  mutate( NewSL = ifelse(setting1, Sepal.Length*10., Sepal.Length/10.) )

但是计算的值有问题,这似乎是 传播的第一行的值

iris2
 Sepal.Length Sepal.Width Petal.Length Petal.Width Species NewSL
 1          5.1         3.5          1.4         0.2  setosa    51
 2          4.9         3.0          1.4         0.2  setosa    51
 3          4.7         3.2          1.3         0.2  setosa    51
 4          4.6         3.1          1.5         0.2  setosa    51
 5          5.0         3.6          1.4         0.2  setosa    51

我当时就明白这是由于长度问题,这显然是 当我用 if_else 替换 ifelse 时识别

iris2 <- iris %>% slice_head(n=5) %>%
  mutate( NewSL = if_else(setting1, Sepal.Length*10., Sepal.Length/10.) )

Error: Problem with mutate() column NewSL. i NewSL = if_else(setting1, Sepal.Length * 10, Sepal.Length/10). x true must be length 1 (length of condition), not 5. Run rlang::last_error() to see where the error occurred.

我可以做这个丑陋的事情来让它发挥作用

rm(iris2)
iris2 <- iris %>% slice_head(n=5) %>%
  mutate( NewSL = if_else( rep(setting1, n()), Sepal.Length*10., Sepal.Length/10.) )

事实上,在我的实际情况中,错误部分是一个常数,所以我必须这样做两次

iris2 <- iris %>% slice_head(n=5) %>%
  mutate( NewSL = if_else( rep(setting1, n()), Sepal.Length*10., rep(10.0, n()) ) )

我的问题是:是否有一种优雅/简洁的整洁方式可以使这项工作在没有rep()技巧的情况下正常工作?

大多数 mutate/if_else 组合的示例在条件部分使用数据集的列, 不是常数,因此在这种情况下长度没有问题

值得注意的是,我还设法使用其他方法获得正确的输出

  1. 使用 R 基本语法
iris2 <- iris
if (setting1) {
  iris2$NewSL=  iris2$Sepal.Length*10.
} else {
  iris2$NewSL = iris2$Sepal.Length/10.
  # or iris2$NewSL = 10.0
}
  • 或者使用条件管道保持 tidyverse 语法,这似乎工作正常,但我发现对于这样简单的情况也相当冗长且可读性较差
  • iris2 <- iris %>% slice_head(n=5) %>%
      {if(setting1) mutate(., NewSL = Sepal.Length*10.) 
        else mutate(., NewSL = Sepal.Length/10.) }
    

    我想知道使用 tidyverse 语法正确执行此操作的最有效方法。 预先感谢您的宝贵时间。

    最佳答案

    ifelse/if_else 用于向量。您应该继续使用您已经确定的 if

    library(dplyr)
    
    setting1 = TRUE
    
    iris %>% 
      slice_head(n=5) %>%
      mutate( NewSL = if(setting1) Sepal.Length*10 else Sepal.Length/10)
    
    #  Sepal.Length Sepal.Width Petal.Length Petal.Width Species NewSL
    #1          5.1         3.5          1.4         0.2  setosa    51
    #2          4.9         3.0          1.4         0.2  setosa    49
    #3          4.7         3.2          1.3         0.2  setosa    47
    #4          4.6         3.1          1.5         0.2  setosa    46
    #5          5.0         3.6          1.4         0.2  setosa    50
    

    关于R - 在 dplyr::mutate/if_else 组合中寻找更好的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70904516/

    相关文章:

    python - R - 使用行级条件变量合并两个 Data.Frame

    r - dplyr concat列存储在变量中(变异和非标准评估)

    r - 如何读取名称相似的文件?

    R dplyr 使用哈希函数(摘要)进行变异,需要 R 对象作为输入

    r - 如何使用R调整x轴字体大小?

    json - httr 库中的 POST 方法与 R 中的特定 header

    r - dplyr 和 POSIXlt 数据的问题

    r - 什么是 select_at()?

    r - 在 R 函数中使用变量作为参数

    r - R中动物园对象的分位数和聚合