Pregunta

Con frecuencia se crea la estadística no paramétrica (loess, la densidad del núcleo, etc.) en los datos que retirarse de una base de datos relacional. Para hacer más fácil la gestión de datos me gustaría volver a almacenar salida R dentro de mi DB. Esto es fácil con tramas de datos simples de números o texto, pero no he encontrado la manera de almacenar objetos R vuelta en mi base de datos relacional. Entonces, ¿hay una manera de almacenar un vector de densidades del núcleo, por ejemplo, de nuevo en una base de datos relacional?

Ahora mismo trabajo en torno a este por el ahorro de los objetos R a un espacio de unidad de red para que otros usuarios pueden cargar los objetos según sea necesario.

¿Fue útil?

Solución

Utilice la función de serialización para convertir cualquier objeto en una cadena R (cruda o carácter), a continuación, almacenar esa cadena. Ver help(serialize).

invertir esta para la recuperación:. Obtener la cadena, entonces unserialize() en un objeto de R

Otros consejos

Una variable ejemplo R, que es bastante complejo:

library(nlme)
model <- lme(uptake ~ conc + Treatment, CO2, random = ~ 1 | Plant / Type)

El método mejor base de datos de almacenamiento para variables R depende de cómo desea utilizarlo.

Necesito hacer análisis dentro de la base de datos sobre los valores

En este caso, es necesario romper el objeto hacia abajo en valores que la base de datos puede manejar de forma nativa. Esto generalmente significa convertirlo en una o más tramas de datos. La forma más sencilla de hacerlo es utilizar el paquete broom.

library(broom)
coefficients_etc <- tidy(model)
model_level_stats <- glance(model)
row_level_stats <- augment(model)

Sólo quiero almacenamiento

En este caso, desea realizar una serie sus variables R. Es decir, la conversión a ser una cadena o un blob binario. Hay varios métodos para ello.


Mis datos tiene que ser accesible por otros programas de R, y debe ser legible por humanos

Se debe almacenar los datos en un formato de texto multiplataforma; Probablemente JSON o YAML. JSON no es compatible con algunos conceptos importantes como Inf; YAML es más general pero el apoyo en R no está tan madura. XML también es posible, pero es demasiado detallado para ser útil para el almacenamiento de grandes matrices.

library(RJSONIO)
model_as_json <- toJSON(model)
nchar(model_as_json) # 17916

library(yaml)
# yaml package doesn't yet support conversion of language objects,
# so preprocessing is needed
model2 <- within(
  model,
  {
     call <- as.character(call)
     terms <- as.character(terms)
  }
)
model_as_yaml <- as.yaml(model2) 
nchar(model_as_yaml) # 14493

Mis datos tiene que ser accesible por otros programas de R, y no necesita ser legible por humanos

Se puede escribir los datos a un formato binario multiplataforma abierto como HFD5. Actualmente soporte para archivos HFD5 (a través de rhdf5 ) está limitado, por lo objetos complejos no son compatibles. (Es probable que tengas que unclass todo.)

library(rhdf5)
h5save(rapply(model2, unclass, how = "replace"), file = "model.h5")
bin_h5 <- readBin("model.h5", "raw", 1e6)
length(bin_h5) # 88291 not very efficient in this case

El paquete let feather que ahorremos tramas de datos en un formato legible por ambos R y Python. Para utilizarlo, primero tendría que convertir el objeto de modelo en tramas de datos, como se describe en la sección anterior escoba en la respuesta.

library(feather)
library(broom)
write_feather(augment(model), "co2_row.feather")  # 5474 bytes
write_feather(tidy(model), "co2_coeff.feather")   # 2093 bytes
write_feather(glance(model), "co2_model.feather") #  562 bytes

Otra alternativa es guardar una versión de texto de la variable (ver apartado anterior) a un archivo comprimido y almacenar sus bytes en la base de datos.

writeLines(model_as_json)
tar("model.tar.bz", "model.txt", compression = "bzip2")
bin_bzip <- readBin("model.tar.bz", "raw", 1e6)
length(bin_bzip) # only 42 bytes!

Mis datos sólo necesita ser accesible por R, y debe ser legible por humanos

Hay dos opciones para convertir una variable en una cadena: serialize y deparse .

p <- function(x)
{
  paste0(x, collapse = "\n")
}

serialize necesidades que se enviará a una conexión de texto, y en lugar de escribir en el archivo, se puede escribir en la consola y capturarlo.

 model_serialized <- p(capture.output(serialize(model, stdout())))
 nchar(model_serialized) # 23830

Uso deparse con control = "all" para maximizar la reversibilidad cuando se re-analizar más adelante.

model_deparsed <- p(deparse(model, control = "all"))
nchar(model_deparsed) # 22036

Mis datos sólo necesita ser accesible por R, y no necesita ser legible por humanos

Los mismos tipos de técnicas que se muestran en las secciones anteriores se puede aplicar aquí. Puede comprimir un serializado o variable y deparsed releerlo como un vector prima.

serialize También puede escribir variables en un formato binario. En este caso, se utiliza más fácilmente con su saveRDS envoltura.

saveRDS(model, "model.rds")
bin_rds <- readBin("model.rds", "raw", 1e6)
length(bin_rds) # 6350

Para sqlite (y posiblemente otros):

CREATE TABLE data (blob BLOB);

Ahora en R:

RSQLite::dbGetQuery(db.conn, 'INSERT INTO data VALUES (:blob)', params = list(blob = list(serialize(some_object)))

Tenga en cuenta la envoltura alrededor list some_object. La salida del serialize es un vector en bruto. Sin list, la instrucción INSERT se ejecuta para cada elemento del vector. Envolviéndolo en una lista permite RSQLite::dbGetQuery a verlo como un elemento.

Para obtener la parte posterior de la base de datos de objetos:

some_object <- unserialize(RSQLite::dbGetQuery(db.conn, 'SELECT blob FROM data LIMIT 1')$blob[[1]])

Lo que sucede es que toma el blob campo (que es una lista desde RSQLite no sabe cuántas filas será devuelto por la consulta). Dado que se devuelve asegura LIMIT 1 única fila 1, lo tomamos con [[1]], que es el vector prima original. Luego hay que unserialize el vector prima para conseguir su objeto.

El uso de textConnection / saveRDS / loadRDS es tal vez el nivel más versátil y de alta:

zz<-textConnection('tempConnection', 'wb')
saveRDS(myData, zz, ascii = T)
TEXT<-paste(textConnectionValue(zz), collapse='\n')

#write TEXT into SQL
...
closeAllConnections()  #if the connection persists, new data will be appended

#reading back:
#1. pull from SQL into queryResult
...
#2. recover the object
recoveredData <- readRDS(textConnection(queryResult$TEXT))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top