Dir*_*tel 11
使用序列化功能将任何R对象转换为(原始或字符)字符串,然后存储该字符串.见help(serialize).
将其反转以进行检索:获取字符串,然后unserialize()转换为R对象.
Ric*_*ton 11
一个示例R变量,它相当复杂:
library(nlme)
model <- lme(uptake ~ conc + Treatment, CO2, random = ~ 1 | Plant / Type)
Run Code Online (Sandbox Code Playgroud)
R变量的最佳存储数据库方法取决于您希望如何使用它.
我需要对值进行数据库内分析
在这种情况下,您需要将对象分解为数据库可以本机处理的值.这通常意味着将其转换为一个或多个数据帧.最简单的方法是使用该broom包.
library(broom)
coefficients_etc <- tidy(model)
model_level_stats <- glance(model)
row_level_stats <- augment(model)
Run Code Online (Sandbox Code Playgroud)
我只想要存储
在这种情况下,您希望序列化您的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
Run Code Online (Sandbox Code Playgroud)
我的数据必须可由R以外的程序访问,并且不需要是人类可读的
您可以将数据写入开放的跨平台二进制格式,如HFD5.目前对HFD5文件(via 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
Run Code Online (Sandbox Code Playgroud)
该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
Run Code Online (Sandbox Code Playgroud)
另一种方法是将变量的文本版本(参见上一节)保存到压缩文件中,并将其字节存储在数据库中.
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!
Run Code Online (Sandbox Code Playgroud)
我的数据只需要R可以访问,并且需要人类可读
将变量转换为字符串有两种选择:serialize和deparse.
p <- function(x)
{
paste0(x, collapse = "\n")
}
Run Code Online (Sandbox Code Playgroud)
serialize 需要发送到文本连接,而不是写入文件,您可以写入控制台并捕获它.
model_serialized <- p(capture.output(serialize(model, stdout())))
nchar(model_serialized) # 23830
Run Code Online (Sandbox Code Playgroud)
deparse与control = "all"以后重新解析时最大化可逆性一起使用.
model_deparsed <- p(deparse(model, control = "all"))
nchar(model_deparsed) # 22036
Run Code Online (Sandbox Code Playgroud)
我的数据只需要由R访问,并且不需要是人类可读的
可以在此处应用前面部分中显示的相同类型的技术.您可以压缩序列化或解压缩的变量,并将其重新读取为原始矢量.
serialize也可以用二进制格式编写变量.在这种情况下,它最容易与其包装使用saveRDS.
saveRDS(model, "model.rds")
bin_rds <- readBin("model.rds", "raw", 1e6)
length(bin_rds) # 6350
Run Code Online (Sandbox Code Playgroud)
对于sqlite(可能还有其他人):
CREATE TABLE data (blob BLOB);
Run Code Online (Sandbox Code Playgroud)
现在R:
RSQLite::dbGetQuery(db.conn, 'INSERT INTO data VALUES (:blob)', params = list(blob = list(serialize(some_object)))
Run Code Online (Sandbox Code Playgroud)
请注意list包装some_object.输出serialize是原始向量.如果没有list,将对每个向量元素执行INSERT语句.将其包含在列表中允许RSQLite::dbGetQuery将其视为一个元素.
要从数据库中恢复对象:
some_object <- unserialize(RSQLite::dbGetQuery(db.conn, 'SELECT blob FROM data LIMIT 1')$blob[[1]])
Run Code Online (Sandbox Code Playgroud)
这里发生的是你取字段blob(这是一个列表,因为RSQLite不知道查询将返回多少行).由于LIMIT 1确保只返回1行,我们将其与[[1]]原始矢量一起使用.然后你需要unserialize原始矢量来获得你的对象.
| 归档时间: |
|
| 查看次数: |
3904 次 |
| 最近记录: |