我有一个从 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
中使用,该函数仅选择仅包含 NA
s 的列。
# 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/