2017-02-05 10 views
14

NAの値をmutate_ifdplyrで0に置き換えます。以下の構文:mutate_ifの正しい構文

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)) 

リターンエラー:

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

この操作のための正しい構文は何ですか?

答えて

6

からsetを使用することができます私はpurrr tutorialからこのトリックを学んだし、それはまたで働きますdplyr。 この問題を解決するための2つの方法があります。
まず、パイプの外にカスタム関数を定義し、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がそれぞれの列です。

21

mutate_ifの "if"は、を選択することを指し、行ではありません。たとえばmutate_if(data, is.numeric, ...)は、データセット内のすべての数値列に対して変換を実行することを意味します。あなたは数値列でゼロですべてのNASを交換したい場合は

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

うまくいけば、代わりに 'if_else'を使用して' tidyverse'に留まり、TRUE、FALSEタイプの一貫性チェックを追加することができます – aurelien

2

我々は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) 
}