numericas - convertir factor en variable numerica r
¿Por qué R cambia el tipo de variable al anteponer los valores de NA a un marco de datos con factores? (5)
Tengo un problema con la forma en que R coacciona los tipos de variables cuando se usa una rbind
de dos data.frames
con valores de NA
. Ilustramos con el ejemplo:
x<-factor(sample(1:3,10,T))
y<-rnorm(10)
dat<-data.frame(x,y)
NAs<-data.frame(matrix(NA,ncol=ncol(dat),nrow=nrow(dat)))
colnames(NAs)<-colnames(dat)
Ahora el objetivo es agregar dat
y NAs
mientras se mantienen los tipos de variables factor
y numeric
de y
. Cuando doy:
dat_forward<-rbind(dat,NAs)
is.factor(dat_forward$x)
esto funciona bien Sin embargo, la dirección hacia atrás con rbind
falla:
dat_backward<-rbind(NAs,dat)
is.factor(dat_backward$x)
is.character(dat_backward$x)
Ahora x
está obligado a nivel de personaje. Estoy confundido, ¿no puede permanecer el tipo de factor incluso si utilizo el otro orden de enlace? ¿Cuál sería un cambio directo en mi código para alcanzar mi objetivo?
Aquí hay una manera bastante simple de obtener las clases de columna correctas:
x <- rbind(dat[1,], NAs, dat)[-1,]
str(x)
# $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
# $ y: num NA NA NA NA NA NA NA NA NA NA ...
De manera más general, si realmente necesita esto, podría crear una función similar a rbind
que tome un argumento adicional que indique el data.frame a cuyas clases de columna le gustaría forzar a todas las demás columnas:
myrbind <- function(x, ..., template=x) {
do.call(rbind, c(list(template[1,]), list(x), list(...)))[-1,]
}
str(myrbind(NAs, dat, template=dat))
# ''data.frame'': 20 obs. of 2 variables:
# $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
# $ y: num NA NA NA NA NA NA NA NA NA NA ...
## If no ''template'' argument is supplied, myrbind acts just like rbind
str(myrbind(dat, NAs))
# ''data.frame'': 20 obs. of 2 variables:
# $ x: Factor w/ 3 levels "1","2","3": 3 3 3 3 2 3 1 1 3 2 ...
# $ y: num 0.303 1.77 -1.38 1.731 0.033 ...
Del mismo modo, podría convertir la columna en NAs
para factor
NAs$x<-factor(NAs$x)
dat_backward<-rbind(NAs,dat)
is.factor(dat_backward$x) # TRUE
is.character(dat_backward$x) # FALSE
Desde ?rbind.data.frame
, leemos: "Luego toma las clases de las columnas del primer marco de datos ...". Esta es la razón por la que está viendo el asunto de la orden en su llamada a rbind
.
Para obtener las clases variables de dat_forward
con el orden de dat_backward
, puede simplemente construir dat_forward
y reordenar las filas:
dat_new = rbind(dat, NAs)[c((nrow(dat)+1):(nrow(dat)+nrow(NAs)), 1:nrow(dat)),]
str(dat_new)
# ''data.frame'': 20 obs. of 2 variables:
# $ x: Factor w/ 3 levels "1","2","3": NA NA NA NA NA NA NA NA NA NA ...
# $ y: num NA NA NA NA NA NA NA NA NA NA ...
Un enfoque sería crear NAs
con los tipos de datos de columna correctos. Esto se puede hacer fácilmente con
NAs <- dat[NA,]
También puede hacer tantas filas como desee con
num.rows <- 30
NAs <- dat[NA,][1:num.rows,]
data.frame
hace muchas cosas incorrectamente cuando se rbind
diferentes tipos juntos, y especialmente cuando eso involucra factores. Comience a usar data.table
(1.8.11+) en su lugar y no tendrá estos problemas:
library(data.table)
dt1 = data.table(dat)
dt2 = data.table(NAs)
sapply(rbind(dt1, dt2), class)
# x y
# "factor" "numeric"
sapply(rbind(dt2, dt1), class)
# x y
# "factor" "numeric"