Tengo un problema al usar data.table: ¿Cómo convierto clases de columna? Aquí hay un ejemplo simple: con data.frame no tengo problemas para convertirlo, con data.table simplemente no sé cómo:
df <- data.frame(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
#One way: http://stackoverflow.com/questions/2851015/r-convert-data-frame-columns-from-factors-to-characters
df <- data.frame(lapply(df, as.character), stringsAsFactors=FALSE)
#Another way
df[, "value"] <- as.numeric(df[, "value"])
library(data.table)
dt <- data.table(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
dt <- data.table(lapply(dt, as.character), stringsAsFactors=FALSE)
#Error in rep("", ncol(xi)) : invalid 'times' argument
#Produces error, does data.table not have the option stringsAsFactors?
dt[, "ID", with=FALSE] <- as.character(dt[, "ID", with=FALSE])
#Produces error: Error in `[<-.data.table`(`*tmp*`, , "ID", with = FALSE, value = "c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)") :
#unused argument(s) (with = FALSE)
¿Me pierdo algo obvio aquí?
Actualización debido a la publicación de Matthew: utilicé una versión anterior antes, pero incluso después de actualizar a 1.6.6 (la versión que uso ahora) todavía recibo un error.
Actualización 2: Digamos que quiero convertir cada columna de la clase "factor" en una columna de "carácter", pero no sé de antemano qué columna es de qué clase. Con un data.frame, puedo hacer lo siguiente:
classes <- as.character(sapply(df, class))
colClasses <- which(classes=="factor")
df[, colClasses] <- sapply(df[, colClasses], as.character)
¿Puedo hacer algo similar con data.table?
Actualización 3:
sessionInfo () R versión 2.13.1 (2011-07-08) Plataforma: x86_64-pc-mingw32 / x64 (64 bits)
locale:
[1] C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] data.table_1.6.6
loaded via a namespace (and not attached):
[1] tools_2.13.1
fuente
data.table
métodos son diferentes a los que son para ellosdata.frame
#Produces error
. +1 de todos modos. No recibo ningún error, ¿qué versión tienes? Sin embargo, hay un problema en esta área, se ha planteado antes, FR # 1224 y FR # 1493 son de alta prioridad para abordar. Sin embargo, la respuesta de Andrie es la mejor manera.invalid times argument
error? Funciona bien para mi. ¿Qué versión tienes?Respuestas:
Para una sola columna:
Usando
lapply
yas.character
:fuente
convcols
de caracteres de columnas.dt[,lapply(.SD,as.numeric),.SDcols=convcols]
es casi instantáneo mientras quedt[,convcols:=lapply(.SD,as.numeric),.SDcols=convcols]
casi se congela R, así que supongo que lo estoy haciendo mal. Graciasset()
por ejemplo,for (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))
[final de la cita]Prueba esto
fuente
Filter
función para identificar las columnas, por ejemplo:changeCols<- names(Filter(is.character, DT))
changeCols <- names(DT)[sapply(DT, is.character)]
.Elevando el comentario de Matt Dowle a la respuesta de Geneorama ( https://stackoverflow.com/a/20808945/4241780 ) para hacerlo más obvio (como se recomienda), puede usar
for(...)set(...)
.Creado el 12/02/2020 por el paquete reprex (v0.3.0)
Vea otro de los comentarios de Matt en https://stackoverflow.com/a/33000778/4241780 para obtener más información.
Editar.
Como se indica en Espen y en
help(set)
,j
puede ser "Nombre (s) de columna (carácter) o número (s) (entero) al que se le asignará un valor cuando las columnas ya existan". Asínames_factors <- c(1L, 3L)
también funcionará.fuente
names_factors
está aquí. Supongo que se tomó de stackoverflow.com/a/20808945/1666063, por lo que esnames_factors = c('fac1', 'fac2')
en este caso, que son los nombres de las columnas, pero también podrían ser números de columna, por ejemplo 1; ncol (dt), que convertiría todas las columnas¡Esta es una MALA manera de hacerlo! Solo dejo esta respuesta en caso de que resuelva otros problemas extraños. Estos mejores métodos son probablemente en parte el resultado de versiones más recientes de data.table ... por lo que vale la pena documentarlo de esta manera. Además, este es un buen ejemplo de
eval
substitute
sintaxis para la sintaxis.que te da
fuente
set()
por ejemplofor (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))
set
embargo, no estoy seguro de si es más apropiado.for(...)set(...)
aquí: stackoverflow.com/a/33000778/403310Probé varios enfoques.
, o de otro modo
fuente
Proporciono una forma más general y segura de hacer estas cosas,
La función
..
se asegura de que obtengamos una variable fuera del alcance de data.table; set_colclass establecerá las clases de tus cols. Puedes usarlo así:fuente
Si tiene una lista de nombres de columna en data.table, desea cambiar la clase de hacer:
fuente
dt[, c(convert_to_character) := lapply(.SD, as.character), .SDcols=convert_to_character]
para asignar por referencia, en lugar de usar la asignación de data.frame más lenta.tratar:
fuente