variable numericas numerica factor convertir categoricas r type-conversion

numericas - Convertir el tipo de varias columnas de un marco de datos a la vez



convertir factor en variable numerica r (8)

Además de la respuesta de @ joran, en la que convert.magic no conservará los valores numéricos en la conversión de factor a número:

convert.magic <- function(obj,types){ out <- lapply(1:length(obj),FUN = function(i){FUN1 <- switch(types[i], character = as.character,numeric = as.numeric,factor = as.factor); FUN1(obj[,i])}) names(out) <- colnames(obj) as.data.frame(out,stringsAsFactors = FALSE) } foo<-data.frame(x=c(1:10), y=c("red", "red", "red", "blue", "blue", "blue", "yellow", "yellow", "yellow", "green"), z=Sys.Date()+c(1:10)) foo$x<-as.character(foo$x) foo$y<-as.character(foo$y) foo$z<-as.numeric(foo$z) str(foo) # ''data.frame'': 10 obs. of 3 variables: # $ x: chr "1" "2" "3" "4" ... # $ y: chr "red" "red" "red" "blue" ... # $ z: num 16777 16778 16779 16780 16781 ... foo.factors <- convert.magic(foo, rep("factor", 3)) str(foo.factors) # all factors foo.numeric.not.preserved <- convert.magic(foo.factors, c("numeric", "character", "numeric")) str(foo.numeric.not.preserved) # ''data.frame'': 10 obs. of 3 variables: # $ x: num 1 3 4 5 6 7 8 9 10 2 # $ y: chr "red" "red" "red" "blue" ... # $ z: num 1 2 3 4 5 6 7 8 9 10 # z comes out as 1 2 3...

Lo siguiente debe preservar los valores numéricos:

## as.numeric function that preserves numeric values when converting factor to numeric as.numeric.mod <- function(x) { if(is.factor(x)) as.numeric(levels(x))[x] else as.numeric(x) } ## The same than in @joran''s answer, except for as.numeric.mod convert.magic <- function(obj,types){ out <- lapply(1:length(obj),FUN = function(i){FUN1 <- switch(types[i], character = as.character,numeric = as.numeric.mod, factor = as.factor); FUN1(obj[,i])}) names(out) <- colnames(obj) as.data.frame(out,stringsAsFactors = FALSE) } foo.numeric <- convert.magic(foo.factors, c("numeric", "character", "numeric")) str(foo.numeric) # ''data.frame'': 10 obs. of 3 variables: # $ x: num 1 2 3 4 5 6 7 8 9 10 # $ y: chr "red" "red" "red" "blue" ... # $ z: num 16777 16778 16779 16780 16781 ... # z comes out with the correct numeric values

Me parece que paso mucho tiempo creando un marco de datos a partir de un archivo, base de datos o algo así, y luego convirtiendo cada columna en el tipo en el que la quería (numérica, factor, carácter, etc.). ¿Hay alguna manera de hacer esto en un solo paso, posiblemente dando un vector de tipos?

foo<-data.frame(x=c(1:10), y=c("red", "red", "red", "blue", "blue", "blue", "yellow", "yellow", "yellow", "green"), z=Sys.Date()+c(1:10)) foo$x<-as.character(foo$x) foo$y<-as.character(foo$y) foo$z<-as.numeric(foo$z)

en lugar de los últimos tres comandos, me gustaría hacer algo como

foo<-convert.magic(foo, c(character, character, numeric))


Encuentro que me encuentro con esto mucho también. Esto se trata de cómo importar datos. Todas las funciones de lectura ... () tienen algún tipo de opción para especificar que no se conviertan cadenas de caracteres en un factor. Lo que significa que las cadenas de texto se mantendrán como caracteres y las que parezcan números se mantendrán como números. Surge un problema cuando tienes elementos que están vacíos y no NA. Pero, de nuevo, na.strings = c ("", ...) debería resolver eso también. Comenzaría analizando detenidamente su proceso de importación y ajustándolo en consecuencia.

Pero siempre puedes crear una función e impulsar esta cadena.

convert.magic <- function(x, y=NA) { for(i in 1:length(y)) { if (y[i] == "numeric") { x[i] <- as.numeric(x[[i]]) } if (y[i] == "character") x[i] <- as.character(x[[i]]) } return(x) } foo <- convert.magic(foo, c("character", "character", "numeric")) > str(foo) ''data.frame'': 10 obs. of 3 variables: $ x: chr "1" "2" "3" "4" ... $ y: chr "red" "red" "red" "blue" ... $ z: num 15254 15255 15256 15257 15258 ...


Me encontré con algo así con el método de búsqueda de RSQLite ... los resultados vuelven como tipos de datos atómicos. En mi caso, fue una marca de fecha y hora lo que me estaba causando frustración. Descubrí que la función setAs es muy útil para ayudar a hacer el trabajo como se espera. Aquí está mi pequeño caso de ejemplo.

##data.frame conversion function convert.magic2 <- function(df,classes){ out <- lapply(1:length(classes), FUN = function(classIndex){as(df[,classIndex],classes[classIndex])}) names(out) <- colnames(df) return(data.frame(out)) } ##small example case tmp.df <- data.frame(''dt''=c("2013-09-02 09:35:06", "2013-09-02 09:38:24", "2013-09-02 09:38:42", "2013-09-02 09:38:42"), ''v''=c(''1'',''2'',''3'',''4''), stringsAsFactors=FALSE) classes=c(''POSIXct'',''numeric'') str(tmp.df) #confirm that it has character datatype columns ## ''data.frame'': 4 obs. of 2 variables: ## $ dt: chr "2013-09-02 09:35:06" "2013-09-02 09:38:24" "2013-09-02 09:38:42" "2013-09-02 09:38:42" ## $ v : chr "1" "2" "3" "4" ##is the dt column coerceable to POSIXct? canCoerce(tmp.df$dt,"POSIXct") ## [1] FALSE ##and the conver.magic2 function fails also: tmp.df.n <- convert.magic2(tmp.df,classes) ## Error in as(df[, classIndex], classes[classIndex]) : ## no method or default for coercing “character” to “POSIXct” ##ittle reading reveals the setAS function setAs(''character'', ''POSIXct'', function(from){return(as.POSIXct(from))}) ##better answer for canCoerce canCoerce(tmp.df$dt,"POSIXct") ## [1] TRUE ##better answer from conver.magic2 tmp.df.n <- convert.magic2(tmp.df,classes) ##column datatypes converted as I would like them! str(tmp.df.n) ## ''data.frame'': 4 obs. of 2 variables: ## $ dt: POSIXct, format: "2013-09-02 09:35:06" "2013-09-02 09:38:24" "2013-09-02 09:38:42" "2013-09-02 09:38:42" ## $ v : num 1 2 3 4


Sé que es bastante tarde para responder, pero usar un ciclo junto con la función de atributos es una solución simple a su problema.

names <-c(x, y, z) chclass <-c("character","character","numeric") for (i in (1:length(names))){ attributes(foo[,(names[i])])$class <-chclass[i] }


Si desea detectar automáticamente el tipo de datos de las columnas en lugar de especificarlo manualmente (por ejemplo, después de la limpieza de los datos, etc.), la función type.convert() puede ayudar.

La función type.convert() toma un vector de caracteres e intenta determinar el tipo óptimo para todos los elementos (lo que significa que debe aplicarse una vez por columna).

df[] <- lapply(df, function(x) type.convert(as.character(x)))

Como amo dplyr , prefiero:

library(dplyr) df <- df %>% mutate_all(funs(type.convert(as.character(.))))


Transformar es lo que pareces describir:

foo <- transform(foo, x=as.character(x), y=as.character(y), z=as.numeric(z))


Una solución data.table algo simple, aunque tomará algunos pasos si cambia a muchos tipos de columnas diferentes.

dt <- data.table( x=c(1:10), y=c(10:20), z=c(10:20), name=letters[1:10]) dt <- dt[, lapply(.SD, as.numeric), by= name]

Esto cambiará todas las columnas excepto las especificadas by por numéricas (o lo que sea que hayas configurado en lapply )


Editar Consulte this pregunta relacionada para obtener algunas simplificaciones y extensiones sobre esta idea básica.

Mi comentario a la respuesta de Brandon usando el switch :

convert.magic <- function(obj,types){ for (i in 1:length(obj)){ FUN <- switch(types[i],character = as.character, numeric = as.numeric, factor = as.factor) obj[,i] <- FUN(obj[,i]) } obj } out <- convert.magic(foo,c(''character'',''character'',''numeric'')) > str(out) ''data.frame'': 10 obs. of 3 variables: $ x: chr "1" "2" "3" "4" ... $ y: chr "red" "red" "red" "blue" ... $ z: num 15254 15255 15256 15257 15258 ...

Para marcos de datos verdaderamente grandes, es posible que desee utilizar lapply lugar del bucle for :

convert.magic1 <- function(obj,types){ out <- lapply(1:length(obj),FUN = function(i){FUN1 <- switch(types[i],character = as.character,numeric = as.numeric,factor = as.factor); FUN1(obj[,i])}) names(out) <- colnames(obj) as.data.frame(out,stringsAsFactors = FALSE) }

Al hacer esto, tenga en cuenta algunas de las complejidades de la coerción de datos en R. Por ejemplo, la conversión de factor a numérico a menudo implica as.numeric(as.character(...)) . Además, tenga en cuenta el comportamiento predeterminado de data.frame() y as.data.frame() de convertir el carácter en factor.