Sostituisci tutti i valori particolari in un data frame


96

Avendo un data frame, come posso sostituire tutti i valori particolari lungo tutte le righe e le colonne. Supponiamo ad esempio che voglia sostituire tutti i record vuoti con NA's (senza digitare le posizioni):

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

    A   B
1      12
2  xyz    
3  jkl 100

Risultato atteso:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100

Risposte:


145

Come questo:

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

14
c'è un modo per farlo in modo efficiente per più di 1 valore !?
PikkuKatja

28
Questo non funziona per i fattori, df[df=="xyz"]<-"abc"verrà visualizzato un errore con "livello di fattore non valido". C'è una soluzione più generale?
glallen

1
non funziona per me. Ho provato questo: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salary == "<= 50K"] <- "49K". Ancora per unico (dfSmallDiscreteCustomSalary $ stipendio) ottengo: [1]> 50K <= 50K
Codious-JR

3
glallen ... se stai cercando di modificare una colonna di fattori con un nuovo valore che è già un fattore, ci sono probabilmente modi più intelligenti di quello che sto per suggerire, ma potresti df $ factorcolumn <- as.character ( df $ factorcolumn), quindi apportare la modifica e terminare riportandola nuovamente in un fattore ... df $ factorcolumn <- as.factor (df $ factorcolumn); sarà completo con il tuo nuovo livello e il valore desiderato.
Joshua Eric Turcotte

Trovato: df.na.replace (df.columns, Map ("" -> "NA")). Show. È interessante notare che non sono in grado di sostituire con null come valore. Ricevo: java.lang.IllegalArgumentException: tipo di valore non supportato java.lang.String (null). su org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram

35

Dato che PikkuKatja e glallen hanno chiesto una soluzione più generale e non posso ancora commentare, scriverò una risposta. Puoi combinare dichiarazioni come in:

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

Per i fattori, il codice di zxzak produce già fattori:

> 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

In caso di problemi, suggerirei di eliminare temporaneamente i fattori.

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

20

Ecco un paio di dplyropzioni:

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'))

Come utilizzeresti la soluzione di tutte le colonne per sostituire diverse stringhe con NA nell'intero set di dati?
Tea Tree,

4

Possiamo usare data.table per ottenerlo rapidamente. Per prima cosa crea df senza fattori,

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

Ora puoi usare

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

e puoi riconvertirlo in un data.frame

setDF(df)

Se vuoi usare solo data.frame e mantenere i fattori è più difficile, devi lavorare con

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

dove valore è il nome di ogni colonna. Devi inserirlo in un ciclo.


2
Perché dovresti usare una libreria esterna per questo caso d'uso? Perché un ciclo se questo può essere risolto con una riga? In che modo la tua risposta aggiunge valore oltre alle risposte già presenti? Non intendo essere duro, penso che mi manchi qualcosa, da qui le domande.
sedotta il

2
È molto più veloce per set di dati di grandi dimensioni. Aggiunge un'alternativa in modo che l'utente possa scegliere il meglio per lui.
skan

0

Se desideri sostituire più valori in un data frame, potrebbe essere utile scorrere tutte le colonne.

Supponi di voler sostituire ""e 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.