在 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(.))
我想在 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(.))