studio - superponer graficas en r
Manejo de tipos de campo en la interacción de la base de datos con R (2)
Uso RMySQL y una base de datos MySQL para almacenar mis conjuntos de datos. A veces los datos se revisan o guardo los resultados en la base de datos también. Para resumir, hay bastante interacción entre R y la base de datos en mi caso de uso.
La mayoría de las veces utilizo funciones de conveniencia como dbWriteTable
y dbReadTable
para escribir y leer mis datos. Desafortunadamente, estos ignoran por completo los tipos de datos R y los tipos de campo MySQL. Quiero decir que esperaría que los campos de fecha de MySQL terminen en una clase Date
o POSIX
. A la inversa, creo que estas clases R se almacenan como un tipo de campo MySQL algo correspondiente. Eso significa que una fecha no debe ser un personaje, no espero distinguir entre float y dobles aquí ...
También traté de usar dbGetQuery
, el mismo resultado allí. ¿Hay algo que me haya extrañado completamente al leer el manual o simplemente no es posible (todavía) en estos paquetes? ¿Qué sería por un buen trabajo?
EDITAR: @mdsummer Intenté encontrar algo más en la documentación, pero solo encontré estas líneas decepcionantes: `Las tablas de MySQL se leen en R como data.frames, pero sin forzar el carácter o los datos lógicos en factores. Del mismo modo, al exportar data.frames, los factores se exportan como vectores de caracteres.
Las columnas enteras generalmente se importan como vectores enteros R, excepto en casos como BIGINT o UNSIGNED INTEGER que se fuerzan a los vectores de doble precisión de R para evitar el truncamiento (actualmente los números enteros de R son cantidades firmadas de 32 bits).
Las variables de tiempo se importan / exportan como datos de caracteres, por lo que debe convertirlos a su representación de fecha / hora favorita.
Aquí hay una función más genérica de la función de @ Matt Bannert
que trabaja con consultas en lugar de tablas:
# Extension to dbGetQuery2 that understands MySQL data types
dbGetQuery2 <- function(con,query){
statement <- paste0("CREATE TEMPORARY TABLE `temp` ", query)
dbSendQuery(con, statement)
desc <- dbGetQuery(con, "DESCRIBE `temp`")[,1:2]
dbSendQuery(con, "DROP TABLE `temp`")
# strip row_names if exists because it''s an attribute and not real column
# otherweise it causes problems with the row count if the table has a row_names col
if(length(grep(pattern="row_names",x=desc)) != 0){
x <- grep(pattern="row_names",x=desc)
desc <- desc[-x,]
}
# replace length output in brackets that is returned by describe
desc[,2] <- gsub("[^a-z]","",desc[,2])
# building a dictionary
fieldtypes <- c("int", "tinyint", "bigint", "float", "double", "date", "character", "varchar", "text")
rclasses <- c("as.numeric", "as.numeric", "as.numeric", "as.numeric", "as.numeric", "as.Date", "as.character", "as.factor", "as.character")
fieldtype_to_rclass = cbind(fieldtypes,rclasses)
map <- merge(fieldtype_to_rclass,desc,by.x="fieldtypes",by.y="Type")
map$rclasses <- as.character(map$rclasses)
#get data
res <- dbGetQuery(con,query)
i=1
for(i in 1:length(map$rclasses)) {
cvn <- call(map$rclasses[i],res[,map$Field[i]])
res[map$Field[i]] <- eval(cvn)
}
return(res)
}
Ok, tengo una solución de trabajo ahora. Aquí hay una función que asigna tipos de campo MySQL a las clases R. Esto ayuda en particular a manejar la fecha del tipo de campo de MySQL ...
dbReadMap <- function(con,table){
statement <- paste("DESCRIBE ",table,sep="")
desc <- dbGetQuery(con=con,statement)[,1:2]
# strip row_names if exists because it''s an attribute and not real column
# otherweise it causes problems with the row count if the table has a row_names col
if(length(grep(pattern="row_names",x=desc)) != 0){
x <- grep(pattern="row_names",x=desc)
desc <- desc[-x,]
}
# replace length output in brackets that is returned by describe
desc[,2] <- gsub("[^a-z]","",desc[,2])
# building a dictionary
fieldtypes <- c("int","tinyint","bigint","float","double","date","character","varchar","text")
rclasses <- c("as.numeric","as.numeric","as.numeric","as.numeric","as.numeric","as.Date","as.character","as.character","as.character")
fieldtype_to_rclass = cbind(fieldtypes,rclasses)
map <- merge(fieldtype_to_rclass,desc,by.x="fieldtypes",by.y="Type")
map$rclasses <- as.character(map$rclasses)
#get data
res <- dbReadTable(con=con,table)
i=1
for(i in 1:length(map$rclasses)) {
cvn <- call(map$rclasses[i],res[,map$Field[i]])
res[map$Field[i]] <- eval(cvn)
}
return(res)
}
Tal vez esta no sea una buena práctica de programación, simplemente no sé nada mejor. Entonces, úsala bajo tu propio riesgo o ayúdame a mejorarla ... Y, por supuesto, solo es la mitad: reading
. Espero tener tiempo para escribir una función de escritura pronto.
Si tienes sugerencias para el diccionario de mapas, házmelo saber :)