我經常在從關係數據庫中抽出的數據上創建非參數統計信息(黃土,內核密度等)。爲了使數據管理更容易,我想將R輸出存回我的數據庫中。使用簡單的數字或文本數據框很容易,但我還沒有想出如何將R對象存儲回關係數據庫。那麼是否有辦法將內核密度向量存儲到關係數據庫中?在關係數據庫中存儲R對象
現在我通過將R對象保存到網絡驅動器空間來解決此問題,以便其他人可以根據需要加載對象。
我經常在從關係數據庫中抽出的數據上創建非參數統計信息(黃土,內核密度等)。爲了使數據管理更容易,我想將R輸出存回我的數據庫中。使用簡單的數字或文本數據框很容易,但我還沒有想出如何將R對象存儲回關係數據庫。那麼是否有辦法將內核密度向量存儲到關係數據庫中?在關係數據庫中存儲R對象
現在我通過將R對象保存到網絡驅動器空間來解決此問題,以便其他人可以根據需要加載對象。
使用序列化功能將任何R對象轉換爲(原始或字符)字符串,然後存儲該字符串。見help(serialize)
。
反向檢索:獲取字符串,然後將unserialize()
轉換爲R對象。
一個例子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
使用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))
對於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
原始矢量來獲取你的對象。
這最後一個似乎_very_低效。 'saveRDS'將對象寫入文件,然後'readBin'將其讀入內存。據我所知,'serialize'直接寫入'connection = NULL'的內存。 – 2017-10-31 00:47:51