Удаление строк, если в нескольких столбцах более 25% NAs

#r #subset #na

Вопрос:

Я хотел бы удалить все строки, которые содержат более 25% NAs в нескольких столбцах. В связи с тем, что это включает в себя около 120 соответствующих столбцов, было бы полезно не указывать их все. Предпочтительно, скорее, что-то вроде: все между columnA и columnZ.

Я пробовал работать с:

 data[!is.na(data$ColumnA:data$ColumnZ), > 0.25]
 

Но это только показало эту ошибку:

Необходимо подмножество столбцов с допустимым вектором индексов.
Логические индексы должны соответствовать размеру индексированного ввода.
Вход x имеет размер 250, но индекс !is.na(данные$ColumnA:данные$ColumnZ) > 0.25 имеет размер 3.

(250-это фактическое количество столбцов в наборе данных)

Я также думал о том, чтобы попробовать drop_na, но это приводит к аналогичной проблеме.

У вас есть какие-нибудь предложения? Заранее спасибо

Комментарии:

1. Не могли бы вы поделиться воспроизводимым образцом ваших данных с помощью dput(head(data)) ?, чтобы другие могли использовать его, чтобы помочь вам.

2. df[rowMeans(is.na(df)) < 0.25, ]

3. @alistaire, я полагаю, вам все равно придется подмножествовать столбцы по имени или индексу, например df[rowMeans(is.na(df[,paste0("Column", LETTERS[1:26])])) < 0.25, ]

Ответ №1:

Вы можете использовать rowMeans(is.na(.)

Данные:

 set.seed(1)
df<-tibble(matrix(sample(c(1, NA), 64, replace=TRUE, prob = c(0.75, 0.25)), nrow=8))

# A tibble: 8 x 1
  `matrix(...)`[,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]
              <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1                 1     1     1     1     1     1     1    NA
2                 1     1     1     1    NA     1     1     1
3                 1    NA     1     1     1     1     1    NA
4                 1     1     1     1    NA    NA    NA     1
5                 1     1     1     1    NA    NA     1    NA
6                 1     1    NA     1     1     1     1     1
7                NA     1     1     1     1     1    NA     1
8                 1     1     1     1     1    NA     1     1
 

Фильтр:

 df%>%filter(rowMeans(is.na(.))<0.25)

# A tibble: 4 x 1
  `matrix(...)`[,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]
              <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1                 1     1     1     1     1     1     1    NA
2                 1     1     1     1    NA     1     1     1
3                 1     1    NA     1     1     1     1     1
4                 1     1     1     1     1    NA     1     1
 

Или с помощью rowwise():

 df%>%
        rowwise()%>%
        filter(mean(is.na(c_across(everything())))<0.25)
 

Ответ №2:

Обычно я решаю задачи такого типа с помощью пакетов tidyverse и naniar.

Вот пример использования встроенного набора данных «airquality» для идентификации строк с более чем 25% NAs (отсутствующие значения):

 library(tidyverse)
library(naniar)

data(airquality)
dat1 <- airquality
miss_case_summary(dat1) %>% 
  filter(pct_miss >= 25)

# A tibble: 2 x 3
#   case n_miss pct_miss
#  <int>  <int>    <dbl>
#1     5      2     33.3
#2    27      2     33.3
 

И исключить эти два случая (строки):

 dat2 <- dat1 %>% 
  slice(-c(5, 27))
 

Если у вас в наборе данных большое количество NAs, вы можете использовать:

 list_of_gt25_NAs <- miss_case_summary(dat1) %>% 
  filter(pct_miss >= 25)

dat2 <- dat1 %>% 
  slice(-c(list_of_gt25_NAs$case))