mutate_if 的正确语法

Correct syntax for mutate_if

我想通过 dplyr 中的 mutate_ifNA 值替换为零。语法如下:

set.seed(1)
mtcars[sample(1:dim(mtcars)[1], 5),
       sample(1:dim(mtcars)[2], 5)] <-  NA

require(dplyr)

mtcars %>% 
    mutate_if(is.na,0)

mtcars %>% 
    mutate_if(is.na, funs(. = 0))

Returns 错误:

Error in vapply(tbl, p, logical(1), ...) : values must be length 1, but FUN(X[[1]]) result is length 32

此操作的正确语法是什么?

mutate_if中的"if"是指选择,不是行。例如 mutate_if(data, is.numeric, ...) 表示对数据集中的所有数字列进行转换。

如果您想将数字列中的所有 NA 替换为零:

data %>% mutate_if(is.numeric, funs(ifelse(is.na(.), 0, .)))

我们可以使用 set 来自 data.table

library(data.table)
setDT(mtcars)
for(j in seq_along(mtcars)){
  set(mtcars, i= which(is.na(mtcars[[j]])), j = j, value = 0)
 }

我从 purrr tutorial 那里学到了这个技巧,它在 dplyr 中也有效。 有两种方法可以解决这个问题:
首先在管道外定义自定义函数,在mutate_if():

中使用
any_column_NA <- function(x){
    any(is.na(x))
}
replace_NA_0 <- function(x){
    if_else(is.na(x),0,x)
}
mtcars %>% mutate_if(any_column_NA,replace_NA_0)

其次,使用~..x的组合。(.x可以用.代替,其他字符不行或符号):

mtcars %>% mutate_if(~ any(is.na(.x)),~ if_else(is.na(.x),0,.x))
#This also works
mtcars %>% mutate_if(~ any(is.na(.)),~ if_else(is.na(.),0,.))

在你的情况下,你也可以使用 mutate_all():

mtcars %>% mutate_all(~ if_else(is.na(.x),0,.x))

使用~,我们可以定义一个匿名函数,而.x.代表变量。在 mutate_if() 的情况下,..x 是每一列。

mtcars %>% mutate_if(is.numeric, replace_na, 0)

或更新的语法

mtcars %>% mutate(across(where(is.numeric),
                         replace_na, 0))

我总是为 dplyr

的 replace_na 功能而苦恼
  replace(is.na(.),0)

这对我来说很适合你正在尝试做的事情。