r

Reemplazar el contenido de la columna de factor en el datagrama R



(7)

Apuesto a que el problema es cuando intentas reemplazar valores por uno nuevo, uno que actualmente no es parte de los niveles del factor existente:

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

Tu ejemplo fue malo, esto funciona:

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

Esto es lo que más probablemente crea el problema que estaba 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

Funcionará si primero aumenta sus niveles de factor:

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

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

Esperaba que lo siguiente funcionara, pero genera un mensaje de advertencia y simplemente inserta NA:

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


En caso de que tenga que reemplazar valores múltiples y si no le importa "refactorizar" su variable con as.factor (as.character (...)) podría intentar lo siguiente:

replace.values <- function(search, replace, x){ stopifnot(length(search) == length(replace)) xnew <- replace[ match(x, search) ] takeOld <- is.na(xnew) & !is.na(x) xnew[takeOld] <- x[takeOld] return(xnew) } iris$Species <- as.factor(search=c("oldValue1","oldValue2"), replace=c("newValue1","newValue2"), x=as.character(iris$Species))


Para las cosas que estás sugiriendo puedes simplemente cambiar los niveles usando los levels :

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


Puede usar la función plyr del paquete plyr para reemplazar valores en un vector de factores.

En su ejemplo para reemplazar el factor virginica por setosa :

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


Una solución más general que funciona con todo el marco de datos a la vez y donde 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 un "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.


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


Yo tuve el mismo problema. Esto funcionó mejor:

Identifique qué nivel quiere modificar: levels(iris$Species)

"setosa" "versicolor" "virginica"

Entonces, setosa es el primero.

Entonces, escribe esto:

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