我们可以将tidyverse 与来自dplyr 的select 一起使用。在select中,指定where中的逻辑表达式,检查待选列中是否有any非NA(!is.na(.))和any非空(nzchar)元素
library(dplyr)
DF_datos %>%
select(where(~ any(!is.na(.))&any(nzchar(.))))
-输出
# V1 V2 V3 V4
#3 aaa aaa
#4 bb bb 70 80
#5 cc cc 80 80
#6 ddd ddd
如果我们只需要检查第 2 行或第 3 行
DF_datos %>%
slice(2:3) %>%
select(where(~ any(!is.na(.))&any(nzchar(.)))) %>%
names %>%
select(DF_datos, .)
或者使用相同的逻辑从base R (R 4.1.0) 使用Filter
Filter(\(x) any(!is.na(x)) & any(nzchar(x)), DF_datos)
-输出
# V1 V2 V3 V4
#3 aaa aaa
#4 bb bb 70 80
#5 cc cc 80 80
#6 ddd ddd
或者对于第 2 行和第 3 行
Filter(\(x) any(!is.na(x)) & any(nzchar(x)), DF_datos[2:3,]) |>
names() |>
{\(x) subset(DF_datos, select = x)}()
或者通过检查复合逻辑表达式的sum是否大于0来使用sum而不是any
Filter(\(x) sum(!is.na(x) & nzchar(x)) > 0, DF_datos)
在早期的R 版本中使用
Filter(function(x) any(!is.na(x)) & any(nzchar(x)), DF_datos)
注意:上述所有选项都很有效,因为它会在列上循环,并且内存效率很高,因为它不会将表达式应用于整个数据集
更新
根据 cmets,如果第 2 行或第 3 行中有任何 NA 或空白,则 OP 想要删除列。
DF_datos$V6 <- c(NA, NA, 80, NA)
DF_datos %>%
slice(2:3) %>%
select(where(~ all(!is.na(.)) & all(nzchar(.)))) %>% names %>%
select(DF_datos, .)
-输出
V1 V2 V3 V4
3 aaa aaa
4 bb bb 70 80
5 cc cc 80 80
6 ddd ddd
或使用Filter
Filter(\(x) all(!is.na(x)) & all(nzchar(x)), DF_datos[2:3,]) |>
names() |>
{\(x) subset(DF_datos, select = x)}()
# V1 V2 V3 V4
#3 aaa aaa
#4 bb bb 70 80
#5 cc cc 80 80
#6 ddd ddd
数据
DF_datos <- structure(list(V1 = c("aaa", "bb", "cc", "ddd"), V2 = c("aaa",
"bb", "cc", "ddd"), V3 = c("", "70", "80", ""), V4 = c("", "80",
"80", ""), V5 = c("", "", "", ""), V6 = c(NA, NA, NA, NA)), row.names = c("3",
"4", "5", "6"), class = "data.frame")