R删除具有特定行条件的Dataframe列
R delete Dataframe columns with specific rows conditions
我有一个包含空值和 NA 值的数据框,如下所示:
> DF_datos
V1 V2 V3 V4 V5 V6
3 aaa aaa NA
4 bb bb 70 80 NA
5 cc cc 80 80 NA
6 ddd ddd NA
我想删除所有在第二行或第三行包含空值或 NA 值的列,而不在数据帧上循环。使用子集功能或类似的东西......
我想要的结果是:
> DF_datos
V1 V2 V3 V4
3 aaa aaa
4 bb bb 70 80
5 cc cc 80 80
6 ddd ddd
我们可以将 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)
注意:以上所有选项都是有效的,因为它在列上循环并且内存效率高,因为这不会将表达式应用于整个数据集
更新
根据评论,OP 希望删除第 2 行或第 3 行中有任何 NA 或空白的列。
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")
使用colSums
-
DF_datos[colSums(is.na(DF_datos) | DF_datos == '') != nrow(DF_datos)]
# V1 V2 V3 V4
#3 aaa aaa
#4 bb bb 70 80
#5 cc cc 80 80
#6 ddd ddd
另一种写法是 -
DF_datos[colSums(!is.na(DF_datos) & DF_datos != '') != 0]
我有一个包含空值和 NA 值的数据框,如下所示:
> DF_datos
V1 V2 V3 V4 V5 V6
3 aaa aaa NA
4 bb bb 70 80 NA
5 cc cc 80 80 NA
6 ddd ddd NA
我想删除所有在第二行或第三行包含空值或 NA 值的列,而不在数据帧上循环。使用子集功能或类似的东西...... 我想要的结果是:
> DF_datos
V1 V2 V3 V4
3 aaa aaa
4 bb bb 70 80
5 cc cc 80 80
6 ddd ddd
我们可以将 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)
注意:以上所有选项都是有效的,因为它在列上循环并且内存效率高,因为这不会将表达式应用于整个数据集
更新
根据评论,OP 希望删除第 2 行或第 3 行中有任何 NA 或空白的列。
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")
使用colSums
-
DF_datos[colSums(is.na(DF_datos) | DF_datos == '') != nrow(DF_datos)]
# V1 V2 V3 V4
#3 aaa aaa
#4 bb bb 70 80
#5 cc cc 80 80
#6 ddd ddd
另一种写法是 -
DF_datos[colSums(!is.na(DF_datos) & DF_datos != '') != 0]