1) drop = FALSE Подписка на data.frame сбрасывает измерения для результатов 1d, если не используется drop = FALSE
, поэтому попробуйте это.(при подписке tibble размеры не отбрасываются.)
# colnames(df[,sapply(df, function(x) any(is.na(x)))])
colnames(df[, sapply(df, function(x) any(is.na(x))), drop = FALSE])
## [1] "a"
или проще:
names(df)[apply(is.na(df), 2, any)]
## [1] "a"
или
names(df)[colSums(is.na(df)) > 0]
## [1] "a"
2) na.rm = TRUE В следующем примере есть NA в первом столбце.Если исключить, что мы получим ответ:
# colnames(tbl_df[,sapply(tbl_df, function(x) any(x == -100))])
colnames(tbl_df[, sapply(tbl_df, function(x) any(x == -100, na.rm = TRUE))])
## [1] "c"
или
names(tbl_df)[colSums(tbl_df == -100, na.rm = TRUE) > 0]
## [1] "c"
или используйте which
names(tbl_df[, sapply(tbl_df, function(x) length(which(x == -100)) > 0)])
## [1] "c"
или
names(tbl_df)[lengths(lapply(as.data.frame(tbl_df == -100), which)) > 0]
## [1] "c"
или используя which(..., arr.ind = TRUE)
names(tbl_df)[ unique(which(tbl_df == -100, arr.ind = TRUE)[, "col"]) ]
## [1] "c"
3) упрощение Мы можем упростить это, выделив общую часть, которая не зависит от данных, в is.bad
:
# colnames(tbl_df[unlist(map(tbl_df, ~any(. %in% c(-99, -100, NA))))])
is.bad <- function(x) any(x %in% c(-99, -100, NA))
names(tbl_df)[ sapply(tbl_df, is.bad) ]
## [1] "a" "b" "c"
или
Filter(function(x) is.bad(tbl_df[[x]]), names(tbl_df))
## [1] "a" "b" "c"
или для другого подхода:
names(tbl_df)[colSums(is.na(tbl_df) | tbl_df == -99 | tbl_df == -100) > 0]
## [1] "a" "b" "c"
4) select_if filter_all
с all_vars
идет строкойrow и выбирает те строки, для которых все столбцы удовлетворяют условию.Вы хотите идти столбец за столбцом, а не строка за строкой.Используйте select_if
вместо:
tbl_df %>%
select_if(~ any(. == -99)) %>%
names
## [1] "a" "b"