Usuń kolumny z dataframe, gdzie wszystkie wartości są NA

Mam problem z ramką danych i sam nie mogłem rozwiązać tego problemu:
Ramka danych ma dowolne właściwości jako kolumny i każdy wiersz reprezentuje jeden zestaw danych.

Pytanie brzmi:
Jak pozbyć się kolumn gdzie dla wszystkich wierszy wartością jest NA?

Author: Jeromy Anglim, 2010-04-15

6 answers

Spróbuj tego:

df <- df[,colSums(is.na(df))<nrow(df)]
 111
Author: teucer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-15 09:12:55

Dwa dotychczas oferowane podejścia zawodzą z dużymi zbiorami danych, ponieważ (między innymi problemy z pamięcią) tworzą is.na(df), który będzie obiektem o tej samej wielkości co df.

Oto dwa podejścia, które są bardziej wydajne w pamięci i czasie

Podejście z wykorzystaniem Filter

Filter(function(x)!all(is.na(x)), df)

I podejście wykorzystujące dane.tabela (dla ogólnej wydajności czasu i pamięci)

library(data.table)
DT <- as.data.table(df)
DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]

Przykłady wykorzystujące Duże dane (30 kolumn, 1E6 wierszy)

big_data <- replicate(10, data.frame(rep(NA, 1e6), sample(c(1:8,NA),1e6,T), sample(250,1e6,T)),simplify=F)
bd <- do.call(data.frame,big_data)
names(bd) <- paste0('X',seq_len(30))
DT <- as.data.table(bd)

system.time({df1 <- bd[,colSums(is.na(bd) < nrow(bd))]})
# error -- can't allocate vector of size ...
system.time({df2 <- bd[, !apply(is.na(bd), 2, all)]})
# error -- can't allocate vector of size ...
system.time({df3 <- Filter(function(x)!all(is.na(x)), bd)})
## user  system elapsed 
## 0.26    0.03    0.29 
system.time({DT1 <- DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]})
## user  system elapsed 
## 0.14    0.03    0.18 
 73
Author: mnel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-27 05:36:40

Innym sposobem byłoby użycie funkcji apply().

Jeśli masz dane.frame

df <- data.frame (var1 = c(1:7,NA),
                  var2 = c(1,2,1,3,4,NA,NA,9),
                  var3 = c(NA)
                  )

Następnie możesz użyć apply(), aby zobaczyć, które kolumny spełniają Twój warunek, więc możesz po prostu zrobić to samo podzbiór, co w odpowiedzi Musa, tylko z podejściem apply.

> !apply (is.na(df), 2, all)
 var1  var2  var3 
 TRUE  TRUE FALSE 

> df[, !apply(is.na(df), 2, all)]
  var1 var2
1    1    1
2    2    2
3    3    1
4    4    3
5    5    4
6    6   NA
7    7   NA
8   NA    9
 14
Author: mropa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-15 12:36:30

dplyr teraz ma select_if czasownik, który może być pomocny tutaj:

library(dplyr)
temp <- data.frame(x = 1:5, y = c(1,2,NA,4, 5), z = rep(NA, 5))
not_all_na <- function(x) any(!is.na(x))
not_any_na <- function(x) all(!is.na(x))

> temp
  x  y  z
1 1  1 NA
2 2  2 NA
3 3 NA NA
4 4  4 NA
5 5  5 NA

> temp %>% select_if(not_all_na)
  x  y
1 1  1
2 2  2
3 3 NA
4 4  4
5 5  5

> temp %>% select_if(not_any_na)
  x
1 1
2 2
3 3
4 4
5 5
 11
Author: zack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 18:24:44
df[sapply(df, function(x) all(is.na(x)))] <- NULL
 5
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 20:05:27

Mam nadzieję, że to również może pomóc. Można by to zrobić w jedną komendę, ale łatwiej było mi ją odczytać dzieląc ją na dwie komendy. Zrobiłem funkcję z poniższą instrukcją i pracowałem błyskawicznie.

naColsRemoval = function (DataTable) { na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )] DataTable [ , unlist (na.cols) := NULL , with = F] }

.SD pozwoli ograniczyć weryfikację do części tabeli, jeśli chcesz, ale przyjmie całą tabelę jako

 1
Author: Luis M. Nieves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-21 12:57:44