结合使用谓词函数整齐地替换缺失值

Tidy replacement of missing values in conjunction with using a predicate function

与使用 a 一起替换 NAs 的推荐整洁方法是什么 谓词函数?

我希望以某种方式利用 tidyr::replace_na()(或类似的预定义缺失值处理程序),但我似乎无法使用 purrrdplyr 使用谓词函数的方式。

library(magrittr)

# Example data:
df <- tibble::tibble(
  id = c(rep("A", 3), rep("B", 3)),
  x = c(1, 2, NA, 10, NA, 30),
  y = c("a", NA, "c", NA, NA, "f")
)

# Works, but needs manual spec of columns that should be handled:
df %>% 
  tidyr::replace_na(list(x = 0))  
#> # A tibble: 6 x 3
#>   id        x y    
#>   <chr> <dbl> <chr>
#> 1 A         1 a    
#> 2 A         2 <NA> 
#> 3 A         0 c    
#> 4 B        10 <NA> 
#> 5 B         0 <NA> 
#> 6 B        30 f

# Doesn't work (at least not in the intended way):
df %>% 
  dplyr::mutate_if(
    function(.x) inherits(.x, c("integer", "numeric")),
    ~tidyr::replace_na(0)  
  )
#> # A tibble: 6 x 3
#>   id        x y    
#>   <chr> <dbl> <chr>
#> 1 A         0 a    
#> 2 A         0 <NA> 
#> 3 A         0 c    
#> 4 B         0 <NA> 
#> 5 B         0 <NA> 
#> 6 B         0 f

# Works, but uses an inline def of the replacement function:
df %>% 
  dplyr::mutate_if(
    function(.x) inherits(.x, c("integer", "numeric")),
    function(.x) dplyr::if_else(is.na(.x), 0, .x)
  )
#> # A tibble: 6 x 3
#>   id        x y    
#>   <chr> <dbl> <chr>
#> 1 A         1 a    
#> 2 A         2 <NA> 
#> 3 A         0 c    
#> 4 B        10 <NA> 
#> 5 B         0 <NA> 
#> 6 B        30 f

# Works, but uses an inline def of the replacement function:
df %>% 
  purrr::modify_if(
    function(.x) inherits(.x, c("integer", "numeric")),
    function(.x) dplyr::if_else(is.na(.x), 0, .x)
  )
#> # A tibble: 6 x 3
#>   id        x y    
#>   <chr> <dbl> <chr>
#> 1 A         1 a    
#> 2 A         2 <NA> 
#> 3 A         0 c    
#> 4 B        10 <NA> 
#> 5 B         0 <NA> 
#> 6 B        30 f

由 reprex 包 (v0.2.1) 创建于 2019-01-21

如果我们使用 ~,则还要指定 .,即

df %>%
   mutate_if(function(.x) inherits(.x, c("integer", "numeric")), 
           ~ replace_na(., 0))
# A tibble: 6 x 3
#  id        x y    
#  <chr> <dbl> <chr>
#1 A         1 a    
#2 A         2 <NA> 
#3 A         0 c    
#4 B        10 <NA> 
#5 B         0 <NA> 
#6 B        30 f    

否则就做

df %>% 
  mutate_if(function(.x) inherits(.x, c("integer", "numeric")), 
      replace_na, replace = 0)
# A tibble: 6 x 3
#  id        x y    
#  <chr> <dbl> <chr>
#1 A         1 a    
#2 A         2 <NA> 
#3 A         0 c    
#4 B        10 <NA> 
#5 B         0 <NA> 
#6 B        30 f    

或者另一种变体是

df %>% 
   mutate_if(funs(inherits(., c("integer", "numeric"))), 
              ~ replace_na(., 0))