r - 如果 R 中的所有值都是 NA,则删除特定列

标签 r tidyverse

我有一个从 R 运行的数据库查询,它可以有多个用 NA 填充的列,其中一些列我需要更进一步,但如果所有值都是 NA,则可以删除一个特定的列。

我通常使用 purrr::discard(~all(is.na(.))) 删除全部为 NA 的列,但由于此数据框可以包含多个 NA 列,我只想删除一个我正在努力使这个特定于 tidyverse 解决方案中的列。

我目前有这个解决方法:

  if(sum(is.na(Orders$Originator)) == nrow(Orders)) {
    
    Orders <- Orders %>%
      select(-Originator)
    
  }

但如果我可以在一个 tidyverse 解决方案中使用它,它会提高可读性。希望有人可以提供帮助!

谢谢!

最佳答案

解决此问题的规范 tidyverse 方法是利用 select(where(...)) 中使用的谓词函数,并将其与按变量名进行的选择相结合。

首先,我们可以编写一个自定义谓词函数以在 where 中使用,该函数仅选择仅包含 NAs 的列。

# custom predicate function
all_na <- function(x) {
  all(is.na(x))
}

我们可以将此函数与一个 bool 表达式一起使用,表示我们想要select y if (read AND &) 它是 all_na:

library(dplyr)

df <- data.frame(
  x = c(1,2,NA),
  y = NA,
  z = c(3,4,5)
)

df %>% 
  select(!(y & where(all_na)))
#>    x z
#> 1  1 3
#> 2  2 4
#> 3 NA 5

要检查这是否真的有效,让我们重新定义 y 使其不仅包含 NA 并且我们将看到这次它没有被取消:

df2 <- data.frame(
  x = c(1,2,NA),
  y = c(1,2,NA),
  z = c(3,4,5)
)

df2 %>% 
  select(!(y & where(all_na)))
#>    x  y z
#> 1  1  1 3
#> 2  2  2 4
#> 3 NA NA 5

我们可以在 where 中使用 lambda 函数来代替自定义函数:

df %>% 
  select(!(y & where(~ all(is.na(.x)))))

reprex package 创建于 2021-12-07 (v0.3.0)


在更大的 tidyverse 中,我们还可以使用 purrr::lmap_at 并选择带有 .at 参数的 y 然后创建一个 lambda 函数说如果 all(is.na(.x)) 然后使用空 list() (= 删除列)否则保留列 .x:

library(purrr)
library(dplyr)

df %>% 
  lmap_at("y", ~ if(all(is.na(.x))) list() else .x)
#> # A tibble: 3 x 2
#>       x     z
#>   <dbl> <dbl>
#> 1     1     3
#> 2     2     4
#> 3    NA     5

reprex package 创建于 2021-12-07 (v2.0.1)

关于r - 如果 R 中的所有值都是 NA,则删除特定列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70260018/

相关文章:

r - 在 R 中编写自定义函数,该函数采用带单位的输入向量

r - 从字符串中提取允许单词变化的数字

r - 如何从列表中生成百分比的数据框摘要

r - dplyr group_by 超过两列的元素

r - 为什么在使用 pivot_wider 时会产生 NA 值?

R - 在坐标对的数据框中获取坐标对的行号

r - ggplot 在使用 `facet_wrap` 时添加正态分布

r - 对每个列组合应用函数

r - 更改日期格式时如何将向量保留为 R 中的日期类

r - 为什么 pivot_longer() 在其输出中只嵌套了四个整数值