Иногда возникает необходимость сохранять объект R в базе данных, что называется, "цельным куском", без отражения его внутренней структуры через атрибуты таблиц.
Подход к решению этой задачи достаточно очевиден: нужно выполнить сериализацию объекта, а затем сохранить его в базе. Позже, когда объект понадобится, его можно извлечь и выполнить десериализацию.
Рассмотрим, как это делается в R на примере типичного "составного" объекта — списка. В виде списков, в частности, сохраняются модели машинного обучения, построенные в пакете caret.
Составим тестовый список
l <- list("super", "important", "stuff")
print(l)
[+](1]]
[1] "super"
[[2]]
[1] "important"
[[3]]
[1] "stuff"
Сериализация объекта с помощью функции serialize
позволяет превратить любой объект R в строку типа raw
. После этого rawToChar
преобразует бинарные данные raw
в символы character
.
l_char <- rawToChar(serialize(l, NULL, TRUE))
nchar(l_char) # сколько всего символов? (пригодится при создании таблицы)
Перейдём к базе данных: создадим её саму и таблицу для хранения списка. Покажем это делается на примере SQLite:
library(RSQLite) # интерфейс к SQLite
# Создаём базу данных.
db <- dbConnect(SQLite(), dbname="test.sqlite")
# Создаём таблицу с 2-мя атрибутами
# * 'id' - первичный ключ,
# * 'list' - собственно список, сохраняемый как 'VARCHAR(100)'.
dbGetQuery(db, 'CREATE TABLE IF NOT EXISTS test
(id INTEGER PRIMARY KEY AUTOINCREMENT,
list VARCHAR(100))'
)
Приятно, что объект, который может иметь весьма сложную структуру, сохраняется в обычном символьном типе данных. В данном случае, в VARCHAR(n)
.
Поместим сериализованный список в таблицу test
# Создаём data.frame для вставки в таблицу БД.
df <- data.frame(lst = l_char)
# Вставляем данные в таблицу БД.
dbGetPreparedQuery(db, 'INSERT INTO test (list) values (:lst)',
bind.data = df)
и удалим из памяти исходный список, а также связанные с ним данные
rm(l, l_char, df)
Прошло некоторое время и нам снова понадобился сохранённый список. Извлекаем его из таблицы:
df2 <- dbGetQuery(db, "SELECT * FROM test")
dbDisconnect(db) # не забываем разорвать соединение с БД.
Восстанавливаем представление списка в R
l2 <- unserialize(charToRaw(df2$list))
и работаем с ним:
print(l2)
[[1]]
[1] "super"
[[2]]
[1] "important"
[[3]]
[1] "stuff"
Читайте также...
- Множество способов сохранения объектов R, в зависимости от поставленной задачи, описано здесь.
Комментарии
comments powered by Disqus