在 tidyverse 中按行等效于 apply()?

Equivalent of apply() by row in the tidyverse?

我想在 data.frame 中插入一个新列,当该行中至少有一个缺失值时该值为 TRUE,否则为 FALSE。

对于这个问题,apply 是一个完美的用例:

编辑 - 添加示例

tab <- data.frame(a = 1:10, b = c(NA, letters[2:10]), c = c(LETTERS[1:9], NA))

tab$missing <- apply(tab, 1, function(x) any(is.na(x)))

但是,我加载了 strict 包,并得到了这个错误:apply() coerces X to a matrix so is dangerous to use with data frames.Please use lapply() instead.

我知道我可以安全地忽略这个错误,但是,我想知道是否有一种方法可以使用 tidyverse 包之一以简单的方式对其进行编码。我尝试使用 dplyr 失败:

tab %>% 
  rowwise() %>% 
  mutate(missing = any(is.na(.), na.rm = TRUE))

如果要避免强制转换为矩阵,可以使用 purrr::pmap,它并行遍历列表的元素并将它们传递给函数:

library(tidyverse)

tab <- data_frame(a = 1:10, 
                  b = c(NA, letters[2:10]), 
                  c = c(LETTERS[1:9], NA))

tab %>% mutate(missing = pmap_lgl(., ~any(is.na(c(...)))))
#> # A tibble: 10 x 4
#>        a     b     c missing
#>    <int> <chr> <chr>   <lgl>
#>  1     1  <NA>     A    TRUE
#>  2     2     b     B   FALSE
#>  3     3     c     C   FALSE
#>  4     4     d     D   FALSE
#>  5     5     e     E   FALSE
#>  6     6     f     F   FALSE
#>  7     7     g     G   FALSE
#>  8     8     h     H   FALSE
#>  9     9     i     I   FALSE
#> 10    10     j  <NA>    TRUE

函数中,需要c将传递给函数...的所有参数拉成一个vector,可以传递给is.na,用[=16折叠] =]. *_lgl 后缀 pmap 将结果简化为布尔向量。

请注意,虽然这避免了对矩阵的强制转换,但它不一定比这样做的方法更快,因为矩阵运算在 R 中得到了高度优化。显式[=28=可能更有意义] 强制转换为矩阵,例如

tab %>% mutate(missing = rowSums(is.na(as.matrix(.))) > 0)

哪个returns一样。

这适用于示例数据:

library(tidyverse)

tab <- data_frame(a = 1:10, 
                  b = c(NA, letters[2:10]), 
                  c = c(LETTERS[1:9], NA))

tab_1 <- tab %>% mutate(missing = ifelse(is.na(b), TRUE, ifelse(is.na(c), TRUE, FALSE)))

> tab_1
    a    b    c missing
1   1 <NA>    A    TRUE
2   2    b    B   FALSE
3   3    c    C   FALSE
4   4    d    D   FALSE
5   5    e    E   FALSE
6   6    f    F   FALSE
7   7    g    G   FALSE
8   8    h    H   FALSE
9   9    i    I   FALSE
10 10    j <NA>    TRUE

您可以使用complete.cases函数:

tab %>% mutate(missing = !complete.cases(.))

要删除具有一个或多个 NA 的行,请使用:

tab %>% filter(complete.cases(.))