Как я могу удалить столбцы, у которых пороговое значение превышает NA? или в процентах (скажем, выше 50%)?
ученик
2
@lovedynasty Вероятно, лучше всего задать отдельный вопрос, если вы еще не сделали этого с момента публикации своего комментария. Но в любом случае вы всегда можете сделать что-то вроде, df[, colSums(is.na(df)) < nrow(df) * 0.5]например, оставить столбцы, по крайней мере, с 50% непустыми.
Киаран Тобин,
2
Люди, работающие с корреляционной матрицей, должны использовать ее, df[, colSums(is.na(df)) != nrow(df) - 1]поскольку диагональ всегда 1
равна
9
Это также можно использовать с функцией select_if dplyr (версия 0.5.0). df %>% select_if(colSums(!is.na(.)) > 0)
Стефан Авей
@MadScone дает мне синтаксическую ошибку в "," для df [, colSums (is.na (df))! = Nrow (df)] и синтаксическую ошибку в "!" в df [colSums (! is.na (df))> 0]. Я что-то
janitor::remove_empty_cols()устарело - используйтеdf <- janitor::remove_empty(df, which = "cols")
André.B
24
Похоже, вы хотите удалить ТОЛЬКО столбцы со ВСЕМИNA s, оставив столбцы с некоторыми строками, у которых есть NAs. Я бы сделал это (но уверен, что есть эффективный векторизованный сценарий:
#set seed for reproducibility
set.seed <- 103
df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )
df
# id nas vals# 1 1 NA NA# 2 2 NA 2# 3 3 NA 1# 4 4 NA 2# 5 5 NA 2# 6 6 NA 3# 7 7 NA 2# 8 8 NA 3# 9 9 NA 3# 10 10 NA 2#Use this command to remove columns that are entirely NA values, it will elave columns where only some vlaues are NA
df[ , ! apply( df , 2 , function(x) all(is.na(x)) ) ]
# id vals# 1 1 NA# 2 2 2# 3 3 1# 4 4 2# 5 5 2# 6 6 3# 7 7 2# 8 8 3# 9 9 3# 10 10 2
Если вы оказались в ситуации, когда вы хотите удалить столбцы с любыми NAзначениями, вы можете просто изменить приведенную allвыше команду на any.
Data.frame имеет два типа столбцов: один, в котором все значения являются числами, а другой, в котором все значения являются NA,
Лоренцо Ригамонти,
Тогда это сработает. Он удаляет только столбцы, в которых есть ВСЕ значения NA.
Саймон О'Хэнлон
1
Хорошее решение. Я бы сделал это apply(is.na(df), 1, all)просто потому, что он немного аккуратнее и is.na()используется для всех, dfа не для одной строки за раз (покажите, будет немного быстрее).
Ciarán Tobin
@MadScone хороший совет - выглядит аккуратнее. Однако вы должны применять к столбцам, а не к строкам.
Саймон О'Хэнлон
@MadScone Изменения блокируются через 5 минут после комментариев. Я не должен волноваться, это не страшно !! :-)
Саймон О'Хэнлон
20
Интуитивный сценарий: dplyr::select_if(~!all(is.na(.))). Он буквально сохраняет только столбцы, в которых отсутствуют все элементы. (чтобы удалить столбцы с отсутствующими элементами).
> df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )
> df %>% glimpse()
Observations: 10
Variables: 3
$ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
$ nas <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
$ vals <int> NA, 1, 1, NA, 1, 1, 1, 2, 3, NA
> df %>% select_if(~!all(is.na(.)))
id vals
11NA22133144NA5516617718829931010NA
Unit: microseconds
expr min lq mean median uq max neval cld
MadSconeF1 154.5178.35257.9396196.05219.255001.01000 a
MadSconeF2 180.4209.75281.2541226.40251.056322.11000 a
BradCannell 2579.42884.903330.37003059.453379.3033667.31000 d
SimonOHanlon 511.0565.00943.3089586.45623.65210338.41000 b
SiboJiang 2558.12853.053377.67023010.303310.0089718.01000 d
jsta 1544.81652.452031.50651706.051872.6511594.91000c
akrun 93.8111.60139.9482121.90135.453851.21000 a
autoplot(mbm)
Иногда первая итерация - это JIT-компиляция, поэтому у нее очень плохое и не очень характерное время. Я думаю, что интересно, что делает больший размер выборки с правильными хвостами распределения. Это хорошая работа.
EngrStudent
Я запустил его еще раз, не был уверен, что изменил сюжет. Что касается раздачи. Мне, вероятно, следует сравнить разные размеры выборок, когда у меня будет время.
DJV
1
Если у вас qqplot ( ggplot2.tidyverse.org/reference/geom_qq.html ) одна из тенденций, такая как "akrun", то я уверен, что есть одна точка, которая сильно отличается от распределения остальных. Остальные показывают, сколько времени потребуется, если вы запустите его несколько раз, но это означает, что произойдет, если вы запустите его один раз. Есть старая пословица: у вас может быть 20-летний опыт работы или 20-кратный опыт работы только за один год.
EngrStudent
очень хорошо! Я удивлен тем, что несколько образцов оказались в крайнем хвосте. Интересно, почему они намного дороже? JIT может быть 1 или 2, но не 20. Условие? Прерывает? Разное? Еще раз спасибо за обновление.
EngrStudent
Пожалуйста, спасибо за мысли. Не знаю, я на самом деле позволил ему работать «свободно».
head(data)
? Вы хотите удалить соответствующие столбцы или строки?Ответы:
Один из способов сделать это:
df[, colSums(is.na(df)) != nrow(df)]
Если количество NA в столбце равно количеству строк, оно должно быть полностью NA.
Или аналогично
df[colSums(!is.na(df)) > 0]
источник
df[, colSums(is.na(df)) < nrow(df) * 0.5]
например, оставить столбцы, по крайней мере, с 50% непустыми.df[, colSums(is.na(df)) != nrow(df) - 1]
поскольку диагональ всегда1
df %>% select_if(colSums(!is.na(.)) > 0)
Вот решение dplyr:
df %>% select_if(~sum(!is.na(.)) > 0)
источник
Другой вариант - это
janitor
пакет:https://github.com/sfirke/janitor
источник
janitor::remove_empty_cols()
устарело - используйтеdf <- janitor::remove_empty(df, which = "cols")
Похоже, вы хотите удалить ТОЛЬКО столбцы со ВСЕМИ
NA
s, оставив столбцы с некоторыми строками, у которых естьNA
s. Я бы сделал это (но уверен, что есть эффективный векторизованный сценарий:#set seed for reproducibility set.seed <- 103 df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) ) df # id nas vals # 1 1 NA NA # 2 2 NA 2 # 3 3 NA 1 # 4 4 NA 2 # 5 5 NA 2 # 6 6 NA 3 # 7 7 NA 2 # 8 8 NA 3 # 9 9 NA 3 # 10 10 NA 2 #Use this command to remove columns that are entirely NA values, it will elave columns where only some vlaues are NA df[ , ! apply( df , 2 , function(x) all(is.na(x)) ) ] # id vals # 1 1 NA # 2 2 2 # 3 3 1 # 4 4 2 # 5 5 2 # 6 6 3 # 7 7 2 # 8 8 3 # 9 9 3 # 10 10 2
Если вы оказались в ситуации, когда вы хотите удалить столбцы с любыми
NA
значениями, вы можете просто изменить приведеннуюall
выше команду наany
.источник
NA
.apply(is.na(df), 1, all)
просто потому, что он немного аккуратнее иis.na()
используется для всех,df
а не для одной строки за раз (покажите, будет немного быстрее).Интуитивный сценарий:
dplyr::select_if(~!all(is.na(.)))
. Он буквально сохраняет только столбцы, в которых отсутствуют все элементы. (чтобы удалить столбцы с отсутствующими элементами).> df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) ) > df %>% glimpse() Observations: 10 Variables: 3 $ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 $ nas <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA $ vals <int> NA, 1, 1, NA, 1, 1, 1, 2, 3, NA > df %>% select_if(~!all(is.na(.))) id vals 1 1 NA 2 2 1 3 3 1 4 4 NA 5 5 1 6 6 1 7 7 1 8 8 2 9 9 3 10 10 NA
источник
Другой вариант с
Filter
Filter(function(x) !all(is.na(x)), df)
ПРИМЕЧАНИЕ: данные из сообщения @Simon O'Hanlon.
источник
Поскольку для меня действительно была важна производительность, я протестировал все вышеперечисленные функции.
ПРИМЕЧАНИЕ: данные из сообщения @Simon O'Hanlon. Только размером 15000 вместо 10.
library(tidyverse) library(microbenchmark) set.seed(123) df <- data.frame(id = 1:15000, nas = rep(NA, 15000), vals = sample(c(1:3, NA), 15000, repl = TRUE)) df MadSconeF1 <- function(x) x[, colSums(is.na(x)) != nrow(x)] MadSconeF2 <- function(x) x[colSums(!is.na(x)) > 0] BradCannell <- function(x) x %>% select_if(~sum(!is.na(.)) > 0) SimonOHanlon <- function(x) x[ , !apply(x, 2 ,function(y) all(is.na(y)))] jsta <- function(x) janitor::remove_empty(x) SiboJiang <- function(x) x %>% dplyr::select_if(~!all(is.na(.))) akrun <- function(x) Filter(function(y) !all(is.na(y)), x) mbm <- microbenchmark( "MadSconeF1" = {MadSconeF1(df)}, "MadSconeF2" = {MadSconeF2(df)}, "BradCannell" = {BradCannell(df)}, "SimonOHanlon" = {SimonOHanlon(df)}, "SiboJiang" = {SiboJiang(df)}, "jsta" = {jsta(df)}, "akrun" = {akrun(df)}, times = 1000) mbm
Полученные результаты:
Unit: microseconds expr min lq mean median uq max neval cld MadSconeF1 154.5 178.35 257.9396 196.05 219.25 5001.0 1000 a MadSconeF2 180.4 209.75 281.2541 226.40 251.05 6322.1 1000 a BradCannell 2579.4 2884.90 3330.3700 3059.45 3379.30 33667.3 1000 d SimonOHanlon 511.0 565.00 943.3089 586.45 623.65 210338.4 1000 b SiboJiang 2558.1 2853.05 3377.6702 3010.30 3310.00 89718.0 1000 d jsta 1544.8 1652.45 2031.5065 1706.05 1872.65 11594.9 1000 c akrun 93.8 111.60 139.9482 121.90 135.45 3851.2 1000 a autoplot(mbm)
mbm %>% tbl_df() %>% ggplot(aes(sample = time)) + stat_qq() + stat_qq_line() + facet_wrap(~expr, scales = "free")
источник