¿Cuál es la forma más rápida / mejor de cambiar una gran cantidad de columnas a numéricas de factor?
Utilicé el siguiente código, pero parece haber reordenado mis datos.
> head(stats[,1:2])
rk team
1 1 Washington Capitals*
2 2 San Jose Sharks*
3 3 Chicago Blackhawks*
4 4 Phoenix Coyotes*
5 5 New Jersey Devils*
6 6 Vancouver Canucks*
for(i in c(1,3:ncol(stats))) {
stats[,i] <- as.numeric(stats[,i])
}
> head(stats[,1:2])
rk team
1 2 Washington Capitals*
2 13 San Jose Sharks*
3 24 Chicago Blackhawks*
4 26 Phoenix Coyotes*
5 27 New Jersey Devils*
6 28 Vancouver Canucks*
¿Cuál es la mejor manera, además de nombrar cada columna como en:
df$colname <- as.numeric(ds$colname)
Respuestas:
Además de la respuesta de Ramnath, el comportamiento que está experimentando se debe a que
as.numeric(x)
devuelve la representación numérica interna del factorx
en el nivel R. Si desea conservar los números que son los niveles del factor (en lugar de su representación interna),as.character()
primero debe convertir al carácter vía según el ejemplo de Ramnath.Su
for
bucle es tan razonable como unaapply
llamada y podría ser un poco más legible en cuanto a cuál es la intención del código. Simplemente cambie esta línea:leer
Esta es la pregunta frecuente 7.10 en las preguntas frecuentes de R.
HTH
fuente
factor
y no funcionó.sapply
omutate_if
parecen ser soluciones de aplicación más general.apply
para ejecutar el bucle y el OP estaba usando unfor
bucle explícitamente. De hecho, todas las respuestas altamente votadas usan elas.numeric(as.character())
idioma.numeric
, pero no funciona a la inversa (para cambiar la clase de varias columnas afactor
). Si usa índices que necesitaunlist()
y cuando se aplica a columnas con caracteres, elimina cada carácter, lo que hace que ya no funcione al volver a colocar la salidastats[,i]
. Consulte la respuesta aquí: stackoverflow.com/questions/45713473/…as.factor()
en lugar deas.numeric(as.character())
aquí y funcionará bien. Por supuesto, si tiene una combinación de columnas, deberá elegir de formai
selectiva, pero eso también es trivial.Debe tener cuidado al cambiar los factores a numéricos. Aquí hay una línea de código que cambiaría un conjunto de columnas de factor a numérico. Supongo aquí que las columnas que se cambiarán a numéricas son 1, 3, 4 y 5 respectivamente. Podrías cambiarlo en consecuencia
cols = c(1, 3, 4, 5); df[,cols] = apply(df[,cols], 2, function(x) as.numeric(as.character(x)));
fuente
x<-as.factor(1:3); df<-data.frame(a=x,y=runif(3),b=x,c=x,d=x)
. No creo queapply
sea apropiado para este tipo de problemas.apply
. Revisa mi edición.unlist
. Yas.character
la conversión en su solución no es necesaria causaapply
convertidosdf[,cols]
acharacter
modoapply(df[,cols], 2, function(x) as.numeric(x))
funcionará también.=
?, ¿por qué no<-
?Esto se puede hacer en una línea, no es necesario un bucle, ya sea un bucle for o una aplicación. Utilice unlist () en su lugar:
# testdata Df <- data.frame( x = as.factor(sample(1:5,30,r=TRUE)), y = as.factor(sample(1:5,30,r=TRUE)), z = as.factor(sample(1:5,30,r=TRUE)), w = as.factor(sample(1:5,30,r=TRUE)) ) ## Df[,c("y","w")] <- as.numeric(as.character(unlist(Df[,c("y","w")]))) str(Df)
Editar: para su código, esto se convierte en:
id <- c(1,3:ncol(stats))) stats[,id] <- as.numeric(as.character(unlist(stats[,id])))
Obviamente, si tiene un marco de datos de una columna y no desea que la reducción de dimensión automática de R lo convierta en un vector, tendrá que agregar el
drop=FALSE
argumento.fuente
recursive
y losuse.names
parámetros deunlist
ambosFALSE
.Df <- tibble::as_tibble(Df)
mutate_if
. O cualquier nuevo enfoque que esté disponible en la próxima iteración dedplyr
...Sé que esta pregunta se resolvió hace mucho tiempo, pero recientemente tuve un problema similar y creo que encontré una solución un poco más elegante y funcional, aunque requiere el paquete magrittr.
library(magrittr) cols = c(1, 3, 4, 5) df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
El
%<>%
operador canaliza y reasigna, lo cual es muy útil para simplificar la limpieza y transformación de datos. Ahora la función de aplicación de lista es mucho más fácil de leer, especificando solo la función que desea aplicar.fuente
df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
df[,cols] %<>% as.numeric(as.character(.))
funciona igualError in [.data.table(Results, , cols) : j (the 2nd argument inside [...]) is a single symbol but column name 'cols' is not found. Perhaps you intended DT[,..cols] or DT[,cols,with=FALSE]. This difference to data.frame is deliberate and explained in FAQ 1.1.
cols <- c("a","b"); df[,cols] %<>% lapply(function(x) as.numeric(as.character(x)))
Aquí tienes algunas
dplyr
opciones:# by column type: df %>% mutate_if(is.factor, ~as.numeric(as.character(.))) # by specific columns: df %>% mutate_at(vars(x, y, z), ~as.numeric(as.character(.))) # all columns: df %>% mutate_all(~as.numeric(as.character(.)))
fuente
Creo que ucfagls descubrió por qué su bucle no funciona.
En caso de que aún no quiera usar un bucle, aquí hay una solución con
lapply
:factorToNumeric <- function(f) as.numeric(levels(f))[as.integer(f)] cols <- c(1, 3:ncol(stats)) stats[cols] <- lapply(stats[cols], factorToNumeric)
Editar. Encontré una solución más simple. Parece que se
as.matrix
convierte en personaje. Entoncesdebe hacer lo que quiera.
fuente
lapply está diseñado para esto
unfactorize<-c("colA","colB") df[,unfactorize]<-lapply(unfactorize, function(x) as.numeric(as.character(df[,x])))
fuente
Encontré esta función en un par de otros hilos duplicados y la he encontrado como una forma elegante y general de resolver este problema. Este hilo aparece primero en la mayoría de las búsquedas sobre este tema, así que lo comparto aquí para ahorrarles algo de tiempo. No me atribuyo ningún mérito por esto, así que consulte las publicaciones originales aquí y aquí para obtener más detalles.
df <- data.frame(x = 1:10, y = rep(1:2, 5), k = rnorm(10, 5,2), z = rep(c(2010, 2012, 2011, 2010, 1999), 2), j = c(rep(c("a", "b", "c"), 3), "d")) convert.magic <- function(obj, type){ FUN1 <- switch(type, character = as.character, numeric = as.numeric, factor = as.factor) out <- lapply(obj, FUN1) as.data.frame(out) } str(df) str(convert.magic(df, "character")) str(convert.magic(df, "factor")) df[, c("x", "y")] <- convert.magic(df[, c("x", "y")], "factor")
fuente
Me gustaría señalar que si tiene NA en cualquier columna, simplemente usar subíndices no funcionará. Si hay NA en el factor, debe utilizar el script de aplicación proporcionado por Ramnath.
P.ej
Df <- data.frame( x = c(NA,as.factor(sample(1:5,30,r=T))), y = c(NA,as.factor(sample(1:5,30,r=T))), z = c(NA,as.factor(sample(1:5,30,r=T))), w = c(NA,as.factor(sample(1:5,30,r=T))) ) Df[,c(1:4)] <- as.numeric(as.character(Df[,c(1:4)]))
Devuelve lo siguiente:
Warning message: NAs introduced by coercion > head(Df) x y z w 1 NA NA NA NA 2 NA NA NA NA 3 NA NA NA NA 4 NA NA NA NA 5 NA NA NA NA 6 NA NA NA NA
Pero:
Df[,c(1:4)]= apply(Df[,c(1:4)], 2, function(x) as.numeric(as.character(x)))
Devoluciones:
> head(Df) x y z w 1 NA NA NA NA 2 2 3 4 1 3 1 5 3 4 4 2 3 4 1 5 5 3 5 5 6 4 2 4 4
fuente
puede usar la
unfactor()
función del paquete "varhandle" del formulario CRAN:library("varhandle") my_iris <- data.frame(Sepal.Length = factor(iris$Sepal.Length), sample_id = factor(1:nrow(iris))) my_iris <- unfactor(my_iris)
fuente
Me gusta este código porque es bastante útil:
data[] <- lapply(data, function(x) type.convert(as.character(x), as.is = TRUE)) #change all vars to their best fitting data type
No es exactamente lo que se pidió (convertir a numérico), pero en muchos casos es incluso más apropiado.
fuente
df$colname <- as.numeric(df$colname)
Intenté de esta manera cambiar un tipo de columna y creo que es mejor que muchas otras versiones, si no va a cambiar todos los tipos de columna
df$colname <- as.character(df$colname)
por lo contrario.
fuente
Tuve problemas para convertir todas las columnas a numéricas con una
apply()
llamada:apply(data, 2, as.numeric)
El problema resulta ser porque algunas de las cadenas tenían una coma, por ejemplo, "1.024,63" en lugar de "1024,63", ya R no le gusta esta forma de formatear los números. Así que los eliminé y luego ejecuté
as.numeric()
:data = as.data.frame(apply(data, 2, function(x) { y = str_replace_all(x, ",", "") #remove commas return(as.numeric(y)) #then convert }))
Tenga en cuenta que esto requiere que se cargue el paquete stringr.
fuente
Eso es lo que funcionó para mí. La
apply()
función intenta coaccionar df a matrix y devuelve NA's.numeric.df <- as.data.frame(sapply(df, 2, as.numeric))
fuente
Según la respuesta de @ SDahm, esta fue una solución "óptima" para mi
tibble
:Esto requiere
dplyr
ymagrittr
.fuente
Probé un montón de estos en un problema similar y seguí obteniendo NA. Base R tiene algunos comportamientos de coerción realmente irritantes, que generalmente se corrigen en los paquetes de Tidyverse. Solía evitarlos porque no quería crear dependencias, pero hacen la vida mucho más fácil que ahora ni siquiera me molesto en intentar descubrir la solución Base R la mayor parte del tiempo.
Aquí está la solución Tidyverse, que es extremadamente simple y elegante:
library(purrr) mydf <- data.frame( x1 = factor(c(3, 5, 4, 2, 1)), x2 = factor(c("A", "C", "B", "D", "E")), x3 = c(10, 8, 6, 4, 2)) map_df(mydf, as.numeric)
fuente
as.numeric(as.character())
conversión para evitar la conversión demasiado común de niveles enteros en lugar de valores a numéricos. Con mucho gusto votaría a favor de esta respuesta si muestra esa opción.