Урок 4 Добавление данных в пакет
В этом уроке мы разберёмся с тем для чего вам может понадобиться добавить в ваш пакет помимо кода функций ещё и данные, и рассмотрим 5 способов это сделать.
Данный урок основан на главе "Data" книги "R Packages (2e)", под авторством Хедли Викхема и Дженни Брайан.
4.3 Конспект
4.3.1 Какие типы данных можно добавить в пакет
Есть 5 способов добавления данных в ваш пакет, в зависимости от того, как эти данные далее будут использоваться:
4.3.2 Экспортируемые данные
Это данные, которые экспорптируются при подключении пакета, и подразумевают их дальнейшее использование конечными пользователями вашего пакета. Зачастую в пакет добавляют несколько наборов данных, которые используются в примерах использования функционала пакета, иногда встречаются пакеты, которые состоят исключительно из данных.
Экспортируемые данные хнятся в виде .rda
файлов в специальном каталоге data/
. Наиболее простой способ включить экспортируемые данные в ваш пакет предоставляет функция usethis::use_data()
.
# создаём набор данных
board_of_directors <- tibble::tibble(
id = 1:5,
name = c("Alex", "John", "Bill", "Stiv", "Michael"),
position = c("CEO", "CTO", "CMO", "CDO", "CFO"),
department = rep("Board of Directors", 5),
year_of_birth = c(1984, 1971, 1987, 1980, 1978),
rate = c(5000, 4200, 3500, 4500, 3500),
office = c("New York", "New York", "Chicago", "Washington", "Washington")
)
# сохраняем его в каталог data
usethis::use_data(board_of_directors)
Функция usethis::use_data()
выполняет следующее:
- Создаёт каталог
data/
, если его ещё нет - Добавляет в каталог
data/
.rda
файлы - Добавляет блок
LazyData: true
в DESCRIPTION файл
Не смотря на то, что у вас есть возможность созранить любе количество наборов данных в один .rda
файл рекомендуется под каждый экспортируемый набор данных создавать отдельный файл в папке data/
.
4.3.3 Внутренние данные
Данные, которые используются искобчительно функциями вашего пакета, являются исключительно технической, а не функциональнйо частью вашего пакета, и для конечного пользователя эти данные недоступны. Соответвенно внутренние данные не экспортируются при подключения пакета. Такие данные хрантся в специальном файле sysdata.rda
в каталоге R/
, т.е. вместе с кодом функций пакета.
Добавить в пакет внутренние данные можно той же функцией usethis::use_data()
, но указав значение аргумента internal = TRUE
.
# создаём наборы данных
board_of_directors <- tibble::tibble(
id = 1:5,
name = c("Alex", "John", "Bill", "Stiv", "Michael"),
position = c("CEO", "CTO", "CMO", "CDO", "CFO"),
department = rep("Board of Directors", 5),
year_of_birth = c(1984, 1971, 1987, 1980, 1978),
rate = c(5000, 4200, 3500, 4500, 3500),
office = c("New York", "New York", "Chicago", "Washington", "Washington")
)
office_coef <- tibble::tibble(
office = c("New York", "Chicago", "Washington"),
coef = c(1.2, 0.85, 1.1)
)
# сохраняем его в файл R/sysdata.rda
usethis::use_data(board_of_directors, office_coef, internal = T)
В отличае от экспортируемых данных, все внутренние наборы данных помещаются в один файл sysdata.rda
, поэтому все их необходимо одновременно указать в функции usethis::use_data()
.
4.3.4 Необработанные данные
Такие данные могут использоваться для предоставления тестовых данных, для примеров использования функций пакета. Например, в пакет readxl
, предназначенный для чтения данных из Excel книг, включены несколько Excel книг, исключительно для того, что бы пользователи могли протестировать его работу, описанную в примерах к функциям пакета.
Необработанные данные необходимо хранить в специальном каталоге по пути inst/extdata
, т.е. создаёте каталог inst
, и внутри него подкаталог extdata
.
dir.create('inst/extdata', recursive = T)
Далее в эту папку добавляете файлы с данными.
для обращения к добавленным необработанным данным необходимо использовать функцию system.file()
, но тут есть один нюанс. Дело в том, что ваш пакет может иметь разные состояни. в момент разработки это просто проект, который может находится в любом месте на вашем жестком диске, а функция system.file()
ищет файлы исключительно в уже установленных пакетах, и если вы её просто будете использовать в вашем пакете, она вернёт пустую строку, вместо пути к файлу с необработанными данными. Но, как вы помните команда load_all()
имитирует процесс загрузки вашего разрабатываемого пакета в память. очень близко к тому, как это делает команда library()
с уже установленными пакетами. Поэтому, для того, что бы команда system.file()
успешно работала в момент разработки вашего пакета, вам всегда необходимо держать пакет в состоянии загруженном в память, т.е. до того, как вы будете тестировать ваши функции нажмите сочетание клавиш Ctrl + Shift + L
.
# Пример обращения к сырым данным пакета firstpackage
# предварительно обязательно надо загрузить пакет в память через load_all()
system.file('extdata', 'board_of_directors.csv', package = 'firstpackage')
4.3.5 Среда пакета
Данный приём используется если вам необходимо динамически изменять состояние вашего пакета. В таком случае вам необходимо создать внутри пакета отдельную среду, добавьте файл aaa.R
в каталог R/
, в котором создайте пустую среду, и добавльте в неё нужные объекты:
Далее в случае необходимости обращения, или изменения значений созданных внутри среды объектов добавьте специальные функции:
#' Report my favorite letters
#' @export
mfl2 <- function() {
the$favorite_letters
}
#' Change my favorite letters
#' @export
set_mfl2 <- function(l = letters[24:26]) {
old <- the$favorite_letters
the$favorite_letters <- l
invisible(old)
}
Код заимствован из книги "R Packages 2e", Hadley Wickham, глава Data, раздел Internal state
Такие данные могут динамически изменяться в ходе одного R сеанса, но при повторном сеансе будут стартовать со своих исходных значений.
4.3.6 Постоянные пользовательские данные
Иногда вам может понадобится хранить какие то данные, которые будут использоваться между различными R сеансами. Например, я в своих пакетах таким образом храню авторизационные данные пользователя, для того, что бы пользователям моих пакетов не требовалось в ходе каждой новой R сессии проходить авторизацию через браузер, они один раз проходят весь процесс авторизации, полученные данные кешируются на жестком диске конечного пользователя, и во всех следующих сеансах читаются из кеша, что поволяет избегать повторной пользовательской авторизации.
Конечно данные, которые будут использоваться между различными R сессиями необходимо хранить локально. на жестком диске пользователя пакета. При этом обязательно необходимо соблюдать спецификацию каталогов принятую для вашей операционной системы, для определения директорий в которых вы будете хранить файлы вашего пакета используйте функцию tools::R_user_dir()
:
-
tools::R_user_dir("pkg", which = "data")
– хранение данных -
tools::R_user_dir("pkg", which = "config")
– хранение конфигов -
tools::R_user_dir("pkg", which = "cache")
– хранение кешированных данных
Но, следует учитывать что функция tools::R_user_dir()
появилась в R 4.0, если вашему пакету необходимо иметь совместимость с более старыми версиями R, то в качестве альтернативного варианта используйте функционал пакета rappdirs
, о котором я отдельно рассказывал в видео уроке "Работа с секретными данными в R".