传递字符串进行变异

Ric*_*c S 1 r dplyr mutate tidyeval

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

我有一个包含几列的数据框,每列至少有一个不适用。这些列的名称存储在character vector中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
}
Run Code Online (Sandbox Code Playgroud)

问题在于,新创建的虚拟变量导致矢量充满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
Run Code Online (Sandbox Code Playgroud)

但我想获得

  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
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*xis 6

问题在于,由于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)))
}
Run Code Online (Sandbox Code Playgroud)

*该rlang软件包是大多数非标准评估dplyr支持的基础,请参见整洁的评估