Ersetzen Sie alle bestimmten Werte in einem Datenrahmen

88

Wie kann ich bei einem Datenrahmen alle bestimmten Werte entlang aller Zeilen und Spalten ersetzen? Angenommen, ich möchte alle leeren Datensätze durch NA's ersetzen (ohne die Positionen einzugeben):

df <- data.frame(list(A=c("", "xyz", "jkl"), B=c(12, "", 100)))

    A   B
1      12
2  xyz    
3  jkl 100

Erwartetes Ergebnis:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100
zxzak
quelle

Antworten:

137

So was:

> df[df==""]<-NA
> df
     A    B
1 <NA>   12
2  xyz <NA>
3  jkl  100
mrip
quelle
14
Gibt es eine Möglichkeit, dies effizient für mehr als einen Wert zu tun?
PikkuKatja
28
Dies funktioniert nicht für Faktoren und df[df=="xyz"]<-"abc"führt zu einem Fehler mit "ungültiger Faktorstufe". Gibt es eine allgemeinere Lösung?
glallen
1
Ich arbeite nicht für mich. Ich habe Folgendes versucht: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ Gehalt == "<= 50K"] <- "49K". Immer noch für einzigartige (dfSmallDiscreteCustomSalary $ Gehalt) bekomme ich: [1]> 50K <= 50K
Codious-JR
3
glallen ... Wenn Sie versuchen, eine Faktorspalte mit einem neuen Wert zu ändern, der bereits ein Faktor ist, gibt es wahrscheinlich klügere Möglichkeiten als das, was ich vorschlagen werde, aber Sie könnten df $ factorcolumn <- as.character ( df $ factorcolumn), nehmen Sie dann Ihre Änderung vor und verwandeln Sie sie abschließend wieder in einen Faktor ... df $ factorcolumn <- as.factor (df $ factorcolumn); Es wird mit Ihrem neuen Level und dem gewünschten Wert abgeschlossen sein.
Joshua Eric Turcotte
Fand es heraus: df.na.replace (df.columns, Map ("" -> "NA")). Show. Interessanterweise kann ich nicht als Wert durch null ersetzen. Ich erhalte: java.lang.IllegalArgumentException: Nicht unterstützter Werttyp java.lang.String (null). bei org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram
32

Da PikkuKatja und glallen nach einer allgemeineren Lösung fragten und ich noch keinen Kommentar abgeben kann, schreibe ich eine Antwort. Sie können Anweisungen wie folgt kombinieren:

> df[df=="" | df==12] <- NA
> df
     A    B
1  <NA> <NA>
2  xyz  <NA>
3  jkl  100

Für Faktoren liefert der Code von zxzak bereits Faktoren:

> df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)))
> str(df)
'data.frame':   3 obs. of  2 variables:
 $ A: Factor w/ 3 levels "","jkl","xyz": 1 3 2
 $ B: Factor w/ 3 levels "","100","12": 3 1 2

Wenn Sie in Schwierigkeiten sind, würde ich vorschlagen, die Faktoren vorübergehend fallen zu lassen.

df[] <- lapply(df, as.character)
sedot
quelle
16

Hier sind einige dplyrOptionen:

library(dplyr)

# all columns:
df %>% 
  mutate_all(~na_if(., ''))

# specific column types:
df %>% 
  mutate_if(is.factor, ~na_if(., ''))

# specific columns:  
df %>% 
  mutate_at(vars(A, B), ~na_if(., ''))

# or:
df %>% 
  mutate(A = replace(A, A == '', NA))

# replace can be used if you want something other than NA:
df %>% 
  mutate(A = as.character(A)) %>% 
  mutate(A = replace(A, A == '', 'used to be empty'))
sbha
quelle
Wie würden Sie die Lösung für alle Spalten verwenden, um mehrere Zeichenfolgen durch NAs im gesamten Datensatz zu ersetzen?
Teebaum
4

Wir können data.table verwenden, um es schnell zu bekommen. Erstellen Sie zuerst df ohne Faktoren,

df <- data.frame(list(A=c("","xyz","jkl"), B=c(12,"",100)), stringsAsFactors=F)

Jetzt können Sie verwenden

setDT(df)
for (jj in 1:ncol(df)) set(df, i = which(df[[jj]]==""), j = jj, v = NA)

und Sie können es wieder in einen data.frame konvertieren

setDF(df)

Wenn Sie nur data.frame verwenden und Faktoren beibehalten möchten, ist es schwieriger, mit ihnen zu arbeiten

levels(df$value)[levels(df$value)==""] <- NA

Dabei ist value der Name jeder Spalte. Sie müssen es in eine Schleife einfügen.

Skan
quelle
2
Warum sollten Sie für diesen Anwendungsfall eine externe Bibliothek verwenden? Warum eine Schleife, wenn dies mit einer Zeile gelöst werden kann? Wie schafft Ihre Antwort einen Mehrwert über die bereits vorhandenen Antworten hinaus? Ich habe nicht vor, hart zu sein, ich glaube, mir fehlt etwas, daher die Fragen.
Sedot
2
Bei großen Datenmengen ist dies viel schneller. Es wird eine Alternative hinzugefügt, damit der Benutzer das Beste für ihn auswählen kann.
Skan
0

Wenn Sie mehrere Werte in einem Datenrahmen ersetzen möchten, kann das Durchlaufen aller Spalten hilfreich sein.

Angenommen, Sie möchten ersetzen ""und 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Olivier Ma
quelle