Ich habe Probleme mit einem Datenrahmen und konnte das Problem nicht wirklich selbst lösen:
Das datenrahmen hat willkürlich eigenschaften als Spalten und jede Reihe repräsentiert einen datensatz.
Die Frage ist:
Wie man spalten für wo loswerden ALLES Zeilen der Wert ist NA?
Versuche dies:
df <- df[,colSums(is.na(df))<nrow(df)]
Die beiden bisher angebotenen Ansätze versagen bei großen Datensätzen, da sie (neben anderen Speicherproblemen) is.na(df)
erstellen, das ein Objekt mit der gleichen Größe wie df
ist.
Hier sind zwei Ansätze, die speicher- und zeiteffizienter sind
Ein Ansatz, der Filter
verwendet
Filter(function(x)!all(is.na(x)), df)
und ein Ansatz unter Verwendung von data.table (für allgemeine Zeit- und Speichereffizienz)
library(data.table)
DT <- as.data.table(df)
DT[,which(unlist(lapply(DT, function(x)!all(is.na(x))))),with=F]
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
dplyr
hat jetzt ein select_if
-Verb, das hier hilfreich sein kann:
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
Eine andere Möglichkeit wäre die Verwendung der Funktion apply()
.
Wenn Sie den Datenrahmen haben
df <- data.frame (var1 = c(1:7,NA),
var2 = c(1,2,1,3,4,NA,NA,9),
var3 = c(NA)
)
dann können Sie mit apply()
sehen, welche Spalten Ihre Bedingung erfüllen, und Sie können einfach dasselbe Subsetting wie in der Antwort von Musa durchführen, nur mit einem apply
-Ansatz.
> !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
df[sapply(df, function(x) all(is.na(x)))] <- NULL
Ich hoffe das kann auch helfen. Man könnte es in einen einzigen Befehl umwandeln, aber ich fand es einfacher zu lesen, indem ich es in zwei Befehle teilte. Ich machte eine Funktion mit der folgenden Anweisung und arbeitete blitzschnell.
naColsRemoval = function (DataTable) {
na.cols = DataTable [ , .( which ( apply ( is.na ( .SD ) , 2 , all ) ) )]
DataTable [ , unlist (na.cols) := NULL , with = F]
}
.SD erlaubt es, die Überprüfung auf einen Teil der Tabelle zu beschränken, wenn Sie möchten
Spät zum Spiel, aber Sie können auch das Paket janitor
verwenden. Diese Funktion entfernt Spalten, die alle NA sind, und kann geändert werden, um auch Zeilen zu entfernen, die alle NA sind.
df <- janitor::remove_empty(df, which = "cols")
Die akzeptierte Antwort funktioniert nicht bei nicht numerischen Spalten. Ab dieser Antwort arbeitet das Folgende mit Spalten, die verschiedene Datentypen enthalten
Filter(function(x) !all(is.na(x)), df)