如何使用dplyr的`across()`语法筛选所有值都为NA的行?

3

如果一个子集的列中所有值都是NA,我想要筛选我的数据。

我在这里找到了一个对于所有列都适用的绝妙答案,但在这种情况下,我想要在筛选操作中排除“wrapper”列。

library(dplyr)

df <- tibble(a = letters[1:3], b = c(NA, NA, 3), c = c(NA, 2, 3), d = letters[1:3])

# works, but I've lost my surrounding columns

df %>%
  select(-one_of(c("a", "d"))) %>%
  filter_all(any_vars(!is.na(.)))

# only works if all columns are all not NA (or vice versa), I've lost my partially NA rows

df %>%
  filter(across(-one_of(c("a", "d")),
                ~ !is.na(.)))

期望结果:

> df[2:3,]
# A tibble: 2 x 4
  a         b     c d    
  <chr> <dbl> <dbl> <chr>
1 b        NA     2 b    
2 c         3     3 c 
3个回答

4
在以前版本的dplyr中,您可以这样使用filter_at
library(dplyr)

df %>% filter_at(vars(-one_of(c("a", "d"))), any_vars(!is.na(.)))

across 没有 any_vars 的直接替代方法,因此一种方法是在此处使用 Reduce

df %>% filter(Reduce(`|`, across(-one_of(c("a", "d")),~!is.na(.))))

# A tibble: 2 x 4
#  a         b     c d    
#  <chr> <dbl> <dbl> <chr>
#1 b        NA     2 b    
#2 c         3     3 c   

2

一个选择是:

df %>%
 rowwise() %>%
 filter(sum(!is.na(c_across(-all_of(c("a", "d"))))) != 0)

  a         b     c d    
  <chr> <dbl> <dbl> <chr>
1 b        NA     2 b    
2 c         3     3 c  

2

我在 vignette("colwise", package = "dplyr") 中找到了一个类似的例子。

rowAny <- function(x) rowSums(x) > 0
df %>% filter(rowAny(across(-c(a,d), ~ !is.na(.))))

# A tibble: 2 x 4
  a         b     c d    
  <chr> <dbl> <dbl> <chr>
1 b        NA     2 b    
2 c         3     3 c  

但我会使用这个,因为它更易读:

rowAll <- function(x) rowSums(x) == length(x)
df %>% filter(!rowAll(across(-c(a,d), is.na)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接