Remplacer toutes les valeurs particulières dans une trame de données

88

Ayant un bloc de données, comment puis-je remplacer toutes les valeurs particulières le long de toutes les lignes et colonnes. Disons par exemple que je veux remplacer tous les enregistrements vides par des NA's (sans taper les positions):

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

    A   B
1      12
2  xyz    
3  jkl 100

Résultat attendu:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100
zxzak
la source

Réponses:

138

Comme ça:

> df[df==""]<-NA
> df
     A    B
1 <NA>   12
2  xyz <NA>
3  jkl  100
mrip
la source
14
y a-t-il un moyen de le faire efficacement pour plus d'une valeur !?
PikkuKatja
28
Cela ne fonctionne pas pour les facteurs, df[df=="xyz"]<-"abc"l'erreur avec "niveau de facteur non valide". Existe-t-il une solution plus générale?
glallen le
1
ne fonctionne pas pour moi. J'ai essayé ceci: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salaire == "<= 50K"] <- "49K". Toujours pour unique (salaire dfSmallDiscreteCustomSalary $) j'obtiens: [1]> 50K <= 50K
Codious-JR
3
glallen ... si vous essayez de modifier une colonne de facteur avec une nouvelle valeur qui est déjà un facteur, il existe probablement des moyens plus intelligents que ce que je suis sur le point de suggérer, mais vous pouvez df $ factorcolumn <- as.character ( df $ factorcolumn), puis effectuez votre modification, et terminez en le transformant à nouveau en facteur ... df $ factorcolumn <- as.factor (df $ factorcolumn); il sera complet avec votre nouveau niveau et la valeur souhaitée.
Joshua Eric Turcotte
Trouvé: df.na.replace (df.columns, Map ("" -> "NA")). Show. Fait intéressant, je ne suis pas en mesure de remplacer par null comme valeur. J'obtiens: java.lang.IllegalArgumentException: type de valeur non pris en charge java.lang.String (null). à org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram
34

Puisque PikkuKatja et glallen ont demandé une solution plus générale et que je ne peux pas encore commenter, j'écrirai une réponse. Vous pouvez combiner des instructions comme dans:

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

Pour les facteurs, le code de zxzak donne déjà des facteurs:

> 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

En cas de problème, je suggérerais de supprimer temporairement les facteurs.

df[] <- lapply(df, as.character)
Sedot
la source
18

Voici quelques dplyroptions:

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
la source
Comment utiliseriez-vous la solution toutes les colonnes pour remplacer plusieurs chaînes par des NA dans l'ensemble de données?
Tea Tree
4

Nous pouvons utiliser data.table pour l'obtenir rapidement. Créez d'abord df sans facteurs,

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

Vous pouvez maintenant utiliser

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

et vous pouvez le reconvertir en data.frame

setDF(df)

Si vous souhaitez uniquement utiliser data.frame et conserver les facteurs, c'est plus difficile, vous devez travailler avec

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

où valeur est le nom de chaque colonne. Vous devez l'insérer dans une boucle.

skan
la source
2
Pourquoi utiliseriez-vous une bibliothèque externe pour ce cas d'utilisation? Pourquoi une boucle si cela peut être résolu avec une seule ligne? Comment votre réponse ajoute-t-elle de la valeur au-delà des réponses déjà présentes? Je n'ai pas l'intention d'être sévère, je pense qu'il me manque quelque chose, d'où les questions.
sedot
2
C'est beaucoup plus rapide pour les grands ensembles de données. Il ajoute une alternative pour que l'utilisateur puisse choisir le meilleur pour lui.
skan
0

Si vous souhaitez remplacer plusieurs valeurs dans un bloc de données, une boucle sur toutes les colonnes peut être utile.

Dites que vous souhaitez remplacer ""et 100:

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