Reemplazar todos los valores particulares en un marco de datos


89

Teniendo un marco de datos, ¿cómo hago para reemplazar todos los valores particulares a lo largo de todas las filas y columnas? Digamos, por ejemplo, que quiero reemplazar todos los registros vacíos con NA's (sin escribir las posiciones):

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

    A   B
1      12
2  xyz    
3  jkl 100

Resultado Esperado:

    A   B
1  NA   12
2  xyz  NA  
3  jkl  100

Respuestas:


139

Me gusta esto:

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

14
¿Hay alguna manera de hacer esto de manera eficiente por más de 1 valor?
PikkuKatja

28
Esto no funciona para los factores, se df[df=="xyz"]<-"abc"producirá un error con "nivel de factor no válido". ¿Existe una solución más general?
glallen

1
no funciona para mí. Intenté esto: dfSmallDiscreteCustomSalary [dfSmallDiscreteCustomSalary $ salario == "<= 50K"] <- "49K". Aún por único (dfSmallDiscreteCustomSalary $ salario) obtengo: [1]> 50K <= 50K
Codious-JR

3
glallen ... si está tratando de modificar una columna de factor con un nuevo valor que ya es un factor, probablemente hay formas más inteligentes de lo que estoy a punto de sugerir, pero podría df $ factorcolumn <- as.character ( df $ factorcolumn), luego haga su modificación y termine convirtiéndola nuevamente en un factor ... df $ factorcolumn <- as.factor (df $ factorcolumn); estará completo con su nuevo nivel y valor deseado.
Joshua Eric Turcotte

Lo encontré: df.na.replace (df.columns, Map ("" -> "NA")). Show. Curiosamente, no puedo reemplazar con nulo como valor. Estoy obteniendo: java.lang.IllegalArgumentException: tipo de valor no admitido java.lang.String (nulo). en org.apache.spark.sql.DataFrameNaFunctions.org $ apache $ spark $ sql $ DataFrameNaFunctions $$ convertToDouble (DataFrameNaFunctions.scala: 434)
sriram

34

Como PikkuKatja y Glallen pidieron una solución más general y aún no puedo comentar, escribiré una respuesta. Puede combinar declaraciones como en:

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

Para los factores, el código de zxzak ya produce factores:

> 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

Si tiene problemas, sugeriría eliminar temporalmente los factores.

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

18

Aquí hay un par de dplyropciones:

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

¿Cómo usaría la solución de todas las columnas para reemplazar varias cadenas por NA en todo el conjunto de datos?
Árbol del té

4

Podemos usar data.table para obtenerlo rápidamente. Primero cree df sin factores,

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

Ahora puedes usar

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

y puede convertirlo de nuevo en un data.frame

setDF(df)

Si solo desea usar data.frame y mantener los factores, es más difícil, debe trabajar con

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

donde valor es el nombre de cada columna. Necesitas insertarlo en un bucle.


2
¿Por qué usaría una biblioteca externa para este caso de uso? ¿Por qué un bucle si esto se puede resolver con una línea? ¿Cómo agrega valor su respuesta más allá de las respuestas ya presentes? No pretendo ser duro, creo que me estoy perdiendo algo, de ahí las preguntas.
sedot

2
Es mucho más rápido para grandes conjuntos de datos. Agrega una alternativa para que el usuario pueda elegir la mejor para él.
skan

0

Si desea reemplazar varios valores en un marco de datos, recorrer todas las columnas puede ser útil.

Digamos que desea reemplazar ""y 100:

na_codes <- c(100, "")
for (i in seq_along(df)) {
    df[[i]][df[[i]] %in% na_codes] <- NA
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.