【问题标题】:Passing a character string to mutate [duplicate]传递一个字符串来改变[重复]
【发布时间】:2019-06-22 15:39:59
【问题描述】:

我已经在 SO 上寻找这个问题的答案,但没有找到解决我的问题的方法。

我有一个包含几列的数据框,每一列至少有一个 NA。这些列的名称存储在字符向量vars_na 中。对于其中的每一个,我想创建一个虚拟变量,如果该观察值缺失,则取值为 0,否则为 1。

下面有一个可重现的玩具示例和我到现在为止使用的代码:

# creation of toy dataset
iris[1:5, 1] <- rep(NA, 5)
iris[1:10, 4] <- rep(NA, 10)
vars_na <- c("Sepal.Length", "Petal.Width")

for(var in vars_na){
  iris <- iris %>% 
    mutate(dummy = ifelse(is.na(!!var), 0, 1)) %>% 
    rename_at(c("dummy"), list(~paste0("dummyna_", var)))
# 'rename_at' is just to differentiate between the several dummies created, 
# and it works correctly
}

问题是新创建的假人导致向量全是1,所以他们没有正确考虑缺失值;确实:

head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species dummyna_Sepal.Length dummyna_Petal.Width
1           NA         3.5          1.4          NA  setosa                    1                   1
2           NA         3.0          1.4          NA  setosa                    1                   1
3           NA         3.2          1.3          NA  setosa                    1                   1
4           NA         3.1          1.5          NA  setosa                    1                   1
5           NA         3.6          1.4          NA  setosa                    1                   1
6          5.4         3.9          1.7          NA  setosa                    1                   1

但我想获得

  Sepal.Length Sepal.Width Petal.Length Petal.Width Species dummyna_Sepal.Length dummyna_Petal.Width
1           NA         3.5          1.4          NA  setosa                    0                   0
2           NA         3.0          1.4          NA  setosa                    0                   0
3           NA         3.2          1.3          NA  setosa                    0                   0
4           NA         3.1          1.5          NA  setosa                    0                   0
5           NA         3.6          1.4          NA  setosa                    0                   0
6          5.4         3.9          1.7          NA  setosa                    1                   0

代码很简单,我相信它应该可以工作。我做错了什么?提前致谢。

【问题讨论】:

    标签: r dplyr tidyeval


    【解决方案1】:

    问题是因为var是一个字符, 像is.na(!!var) 这样的东西最终会变成像is.na("Sepal.Length") 这样的东西, 这总是错误的。

    您可以使用rlang::sym* 将字符转换为可由mutate 评估的符号,例如:

    for (var in vars_na) {
      var_sym <- rlang::sym(var)
      new_name <- rlang::sym(paste0(var, "_na"))
    
      iris <- iris %>%
        mutate(!!new_name := as.integer(!is.na(!!var_sym)))
    }
    

    *rlang 包是 dplyr 支持的大多数非标准评估的基础, 见tidy evaluation

    【讨论】:

    • 呸,有时我会看到quotequosym。什么时候用什么?我没能用quo 完成它...
    • @DSGym 要理解这一切并不容易,我花了很多时间试错。对于那些特定的:quote 是基数 R,quo 类似但来自 rlang 并且还捕获环境,sym 专门用于从字符转换为符号(而 quote/quo 可以捕获性格也是)。一定要阅读那个整洁的评估链接,它不会太长。
    • @Alexis 非常感谢您的建议,我认为对这些概念有一个不错的理解,但显然我必须更多地研究它。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 1970-01-01
    • 2020-03-21
    • 2013-05-19
    • 2015-03-30
    相关资源
    最近更新 更多