2012-08-04 11 views
32

Necesito reemplazar los niveles de una columna de factores en un marco de datos. Usando el conjunto de datos iris como ejemplo, ¿cómo reemplazaría cualquier celda que contenga virginica con setosa en la columna Especies?Reemplazar el contenido de la columna de factores en el marco de datos R

me espera el siguiente a trabajar, pero genera un mensaje de advertencia y simplemente inserta AN:

iris$Species[iris$Species == 'virginica'] <- 'setosa' 
+0

Su ejemplo con 'iris' simplemente funciona. ¿Puedes replicar tu problema de alguna otra manera? Por el momento es difícil entender lo que quieres hacer. – Andrie

+0

Funciona para mí.¿Qué mensaje de advertencia obtienes? – sgibb

+1

Funcionó con iris cuando lo intentaba de nuevo. Sin embargo, la aplicación de lo mismo a mi conjunto de datos le da a esto: Mensaje de advertencia: En '[<-. Factor' (' * tmp * ', x $ Hweet ==" hweet ", value = c (NA_integer_,: nivel de factor no válido, NA generado – luciano

Respuesta

68

apuesto a que el problema es cuando usted está tratando de reemplazar los valores por uno nuevo, uno que no lo es Actualmente parte de los niveles del factor de existente:

levels(iris$Species) 
# [1] "setosa"  "versicolor" "virginica" 

Su ejemplo fue mala, esto funciona:

iris$Species[iris$Species == 'virginica'] <- 'setosa' 

Esto es lo más probable que crea el problema que estaban viendo con sus propios datos:

iris$Species[iris$Species == 'virginica'] <- 'new.species' 
# Warning message: 
# In `[<-.factor`(`*tmp*`, iris$Species == "virginica", value = c(1L, : 
# invalid factor level, NAs generated 

que va a funcionar si primero aumentar sus niveles de factor:

levels(iris$Species) <- c(levels(iris$Species), "new.species") 
iris$Species[iris$Species == 'virginica'] <- 'new.species' 
+10

pero si quieres reemplazar la especie A con la especie B estarías mejor con 'levels (iris $ Species) [match ("oldspecies", levels (iris $ Species))] <- "newspecies" ' –

+0

@flodel - exactamente – luciano

+2

+1 Buena respuesta. ¿De dónde sacaste tu máquina de lectura mental? :-) – Andrie

8

Para las cosas que usted está sugiriendo sólo puede cambiar los niveles con el levels:

levels(iris$Species)[3] <- 'new' 
+0

¿Hay alguna Una forma de hacerlo en múltiples columnas? Por ejemplo, tengo varias columnas con 'TRU E 'y' FALSE 'valores que quiero recodificar a' 0 ',' 1 ' – UD1989

+1

@ UD1989, simplemente use algo como: 'mydf [] <- lapply (mydf, as.numeric)' –

8

puede utilizar la función de la revalue packa ge plyr para reemplazar valores en un vector de factores.

En su ejemplo para sustituir al factor virginica por setosa:

data(iris) 
library(plyr) 
revalue(iris$Species, c("virginica" = "setosa")) -> iris$Species 
+0

¿Qué pasa si no lo hago? t tiene el valor anterior? // y no quiero recuperar el valor anterior solo para usarlo en este método –

2

que tenían el mismo problema. Esto funcionó mejor:

Identificar qué nivel desea modificar: levels(iris$Species)

"setosa" "versicolor" "virginica" 

Así, setosa el primero.

Luego, escribe esto:

 levels(iris$Species)[1] <-"new name" 
1

Una solución más general que trabaja con toda la trama de datos a la vez y en el que no tiene que agregar nuevos niveles de factores es:

data.mtx <- as.matrix(data.df) 
data.mtx[which(data.mtx == "old.value.to.replace")] <- "new.value" 
data.df <- as.data.frame(data.mtx) 

Una buena característica de este código es que puede asignar tantos valores como tenga en su marco de datos original a la vez, no solo uno "new.value", y los nuevos valores pueden ser valores aleatorios. De este modo, puede crear un nuevo marco de datos aleatorio completo con el mismo tamaño que el original.

0

Usando dlpyr::mutate y forcats::fct_recode:

library(dplyr) 
library(forcats) 

iris <- iris %>% 
    mutate(Species = fct_recode(Species, 
    "Virginica" = "virginica", 
    "Versicolor" = "versicolor" 
)) 

iris %>% 
    count(Species) 

# A tibble: 3 x 2 
    Species  n 
     <fctr> <int> 
1  setosa 50 
2 Versicolor 50 
3 Virginica 50 
Cuestiones relacionadas