我经常在从关系数据库中提取的数据上创建非参数统计(黄土,内核密度等)。为了使数据管理更容易,我想将R输出存储在我的数据库中。使用简单的数字或文本数据框很容易,但我还没有弄清楚如何将R对象存储回我的关系数据库中。那么有没有办法将内核密度的向量存储回关系数据库?
现在我通过将R对象保存到网络驱动器空间来解决此问题,以便其他人可以根据需要加载对象。
答案 0 :(得分:10)
使用序列化功能将任何R对象转换为(原始或字符)字符串,然后存储该字符串。请参阅help(serialize)
。
将其反转以进行检索:获取字符串,然后将unserialize()
转换为R对象。
答案 1 :(得分:10)
示例R变量,相当复杂:
library(nlme)
model <- lme(uptake ~ conc + Treatment, CO2, random = ~ 1 | Plant / Type)
R变量的最佳存储数据库方法取决于您希望如何使用它。
我需要对值进行数据库内分析
在这种情况下,您需要将对象分解为数据库可以本机处理的值。这通常意味着将其转换为一个或多个数据帧。最简单的方法是使用broom
包。
library(broom)
coefficients_etc <- tidy(model)
model_level_stats <- glance(model)
row_level_stats <- augment(model)
我只想存储
在这种情况下,您希望序列化R变量。也就是说,将它们转换为字符串或二进制blob。有几种方法可供选择。
我的数据必须可由R以外的程序访问,并且必须是人类可读的
您应该以跨平台文本格式存储数据;可能是JSON或YAML。 JSON不支持像Inf
这样的一些重要概念; YAML更为通用,但R中的支持并不那么成熟。 XML也是可能的,但是对于存储大型数组来说太冗长了。
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
我的数据必须可由R以外的程序访问,并且不需要是人类可读的
您可以将数据写入开放的跨平台二进制格式,如HFD5。目前对HFD5文件的支持(通过rhdf5
)是有限的,因此不支持复杂对象。 (你可能需要unclass
一切。)
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
feather
包允许您以R和Python可读的格式保存数据帧。要使用它,首先必须将模型对象转换为数据框,如答案前面的扫帚部分所述。
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
另一种方法是将变量的文本版本(参见上一节)保存到压缩文件中,并将其字节存储在数据库中。
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!
我的数据只需要R可以访问,并且需要是人类可读的
将变量转换为字符串有两种选择:serialize
和deparse
。
p <- function(x)
{
paste0(x, collapse = "\n")
}
需要将 serialize
发送到文本连接,而不是写入文件,您可以写入控制台并捕获它。
model_serialized <- p(capture.output(serialize(model, stdout())))
nchar(model_serialized) # 23830
将deparse
与control = "all"
一起使用,以便在以后重新解析时最大限度地提高可逆性。
model_deparsed <- p(deparse(model, control = "all"))
nchar(model_deparsed) # 22036
我的数据只需要R可以访问,并且不需要是人类可读的
此处可以应用前面部分中显示的相同类型的技术。您可以压缩序列化或解压缩的变量,并将其重新读取为原始矢量。
serialize
也可以用二进制格式编写变量。在这种情况下,它最容易与其包装saveRDS
一起使用。
saveRDS(model, "model.rds")
bin_rds <- readBin("model.rds", "raw", 1e6)
length(bin_rds) # 6350
答案 2 :(得分:5)
对于sqlite
(可能还有其他人):
CREATE TABLE data (blob BLOB);
现在在R
:
RSQLite::dbGetQuery(db.conn, 'INSERT INTO data VALUES (:blob)', params = list(blob = list(serialize(some_object)))
请注意list
周围的some_object
包装器。 serialize
的输出是原始向量。如果没有list
,将对每个向量元素执行INSERT语句。将其包含在列表中允许RSQLite::dbGetQuery
将其视为一个元素。
从数据库中取回对象:
some_object <- unserialize(RSQLite::dbGetQuery(db.conn, 'SELECT blob FROM data LIMIT 1')$blob[[1]])
这里发生的是你取字段blob
(这是一个列表,因为RSQLite不知道查询将返回多少行)。由于LIMIT 1
只确保返回1行,因此我们将[[1]]
与原始矢量一起使用。然后你需要unserialize
原始向量来获取你的对象。
答案 3 :(得分:2)
使用textConnection / saveRDS / loadRDS可能是最通用和最高级别的:
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))
答案 4 :(得分:2)
[100%的工作-2020年2月27日]
说明: 如果要将模型存储到POSTGRES表中,然后查询并加载它,请执行以下步骤。重要的部分是ascii = TRUE,否则在序列化时会产生错误
db <- pgsql_connect #connection to your database
serialized_model <- rawToChar(serialize(model_fit, NULL, ascii=TRUE))
insert_query <-'INSERT INTO table (model) VALUES ($1)'
rs <- dbSendQuery(db, insert_query, list(serialized_model))
dbClearResult(rs)
serialized_model <- dbGetQuery(db, "select model from table order by created_at desc limit 1")
model_fit2 <- unserialize(charToRaw(as.character(serialized_model[,c('model')])))
model_fit2