Настройка и старт R-сессии
Старт R-сессии — достаточно сложный процесс, включающий в себя подгрузку переменных окружения, пользовательских скриптов конфигураций сессии, а также включение различных опций, подгрузку данных и истории предыдущей сессии и т. д.
Томас Лин Пендерсен нарисовал исчерпывающую схему процесса старта R-сессии:
Переменные окружения (.Renviron)
Первое, что происходит при старте сессии, — это поиск и чтение переменных окружения. В этих переменных обычно хранятся различные пути (к пакетам, к интерпретатору R, к временным файлам), настройки локали (кодировки, форматы даты, времени, валюты и прочее), информация о системе и прочее. Нередко в переменных окружения рекомендуется хранить также и различные токены авторизации: таким образом они будут использоваться в R-сессии, но не будут присутствовать в явном виде в скриптах.
Полный список переменных окружения, которые могут повлиять на R-сессию, можно увидеть в документации по пакету base
по запросу ?'environment variables'
. Список уже используемых в сессии переменных и их значений можно увидеть с помощью команды Sys.getenv()
, в том числе и значение конкретной переменной:
# первые пять переменных окружения из списка
Sys.getenv()[1:5]
## _R_CHECK_COMPILATION_FLAGS_KNOWN_
## -Wformat -Werror=format-security -Wdate-time
## CLICOLOR_FORCE 1
## DBUS_SESSION_BUS_ADDRESS
## unix:path=/run/user/1000/bus
## DEFAULTS_PATH /usr/share/gconf/plasma.default.path
## DERBY_HOME /usr/lib/jvm/java-17-oracle/db
# смотрим путь к интерпретатору R и пакетам
Sys.getenv(c("R_HOME", "R_LIBS_USER"))
## R_HOME R_LIBS_USER
## "/usr/lib/R" "~/R/x86_64-pc-linux-gnu-library/4.1"
В том числе можно адресно вызвать значения локали с помощью Sys.getlocale()
. В рамках сессии локаль можно изменить с функцией Sys.setlocale()
(стоит учитывать, что названия локалей платформозависимы).
# смотрим используемые в сессии параметры локали
Sys.getlocale()
## [1] "LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=ru_RU.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=ru_RU.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=ru_RU.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=ru_RU.UTF-8;LC_IDENTIFICATION=C"
Поиск переменных происходит по цепочке (на примере структуры папок Linux, для Windows будут другие адреса):
файл, указанный в
R_ENVIRON
илиR_HOME/etc/Renviron.site
, — переменные окружения, которые используются для всех пользователей рабочей станции;файл, указанный в
R_ENVIRON_USER
или.Renviron
, находящийся в папке проекта, — набор переменных окружения и их возможных значений, которые используются в этом проекте (например, токены авторизации);файл
/home/.Renviron
, находящийся в папке пользователя, — набор переменных окружения и их возможных значений, которые используются во всех проектах этого пользователя.
Если файлы .Renviron
отсутствуют и в R_ENVIRON/R_ENVIRON_USER
ничего не указано, то используются переменные, указанные в R_HOME/etc/Renviron.site
. При необходимости можно создать свой файл .Renviron
(стоит учитывать, что если есть .Renviron
проекта, то .Renviron
пользователя будет проигнорирован, так как он ниже в иерархии процесса загрузки). Формат файла простой: пара VARIABLE=value
, одна пара на строку. Например, R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'
. Фактически это обычный текстовый файл со строгой структурой.
Скрипты конфигурации .Rprofile
После загрузки переменных окружения при старте R-сессии загружается файл конфигурации сессии, Rprofile.site / .Rprofile. Процесс схож с загрузкой переменных окружения: сначала поиск файла, задающего параметры сессии для всех пользователей рабочей станции в R_PROFILE
или R_HOME/etc/Rprofile.site
. Если файла нет, то поиск файла .Rprofile
продолжается в R_PROFILE_USER
и папке проекта, и только потом в домашней папке пользователя. Эти файлы действуют на все сессии проекта или на все сессии пользователя соответственно.
Чаще всего используют .Rprofile
-скрипты, так как хорошей практикой считается максимально сужать область действия файлов конфигураций сессии. Временами можно даже найти на тематических форумах треды (в частности, на Stackoverflow), в которых пользователи делятся своими конфигурациями. В отличие от .Renviron
, скрипты .Rprofile
содержат код на R и могут включать в себя установку определенных опций, объявление или вызов функций. В .Rprofile
также можно объявить функции, которые будут выполняться при старте или при завершении работы (функции .Start()
и .Last()
соответственно).
Вот так выглядит пример Rprofile.site
из документации, где устанавливается репозиторий по умолчанию:
Также пример из документации для .Rprofile
. Здесь задаётся зерно для генерации псевдослучайных чисел, опции отображения (количество колонок при выводе на печать, количество значимых знаков и нужно ли отображать маркеры значимости различий). Выражение .First <- function() cat("\n Welcome to R!\n\n")
задаёт печать в консоли сообщения Welcome to R!
при загрузке сессии. Выражение .Last <- function() cat("\n Goodbye!\n\n")
напечатает Goodbye!
при завершении сессии:
options(width=65, digits=5)
options(show.signif.stars=FALSE)
setHook(packageEvent("grDevices", "onLoad"),
function(...) grDevices::ps.options(horizontal=FALSE))
set.seed(1234)
.First <- function() cat("\n Welcome to R!\n\n")
.Last <- function() cat("\n Goodbye!\n\n")
Несмотря на очевидную полезность .Rprofile
(да и .Renviron
тоже), их следует осмотрительно использовать. В частности, могут возникнуть проблемы с совместным использованием скриптов: если какой-то скрипт написан с учётом того, что в .Rprofile
объявляются пользовательские функции, то в любой другой сессии, где нет такого же файла конфигурации сессии, скрипт работать не будет. Например, нередко в .Rprofile
пишут объявление функций типа %nin% <- function(x, y) !(x %in% y)
или выставляют опцию options(stringsAsFactors = FALSE)
(эта опция была актуальна для версий ниже 4.0, в которой её сделали по умолчанию).
Обычно при создании скриптов конфигурации меняют те элементы, которые не влияют напрямую на работу скрипта, но могут сделать жизнь проще. Типовые решения:
указывают ближайшее зеркало CRAN;
меняют символ начала строки в консоли (как правило, c
>
на>>
или#
);устанавливают опции отображения (количество значимых знаков для
print()
, запрет на отображение чисел в scientific-формате и т. д.);задают определённые действия при старте и завершении сессии, например, при завершении сессии задают запись
sessionInfo()
в отдельный файл;в редких случаях указывают загрузку часто используемых пакетов и перегружают базовые функции, в частности, мне как-то приходилось переопределять и внедрять в
source()
элементы трассировки ошибок с помощьюtraceback()
, а также настраивать цвет сообщений об ошибках.
Нередко рекомендуется все объявляемые .Rprofile
функции сопровождать проверкой на то, каким образом будет выполняться скрипт, интерактивно в консоли или выполнением R-скрипта через source()
или eval()
. Например:
# опция для всех процессов сессии, как интерактивных, так и неинтерактивных
options(repos = c(CRAN = "https://cran.rstudio.org"))
# только если работа идёт в интерактивном режиме
if (interactive()) {
options(scipen = 999)
}
Настройки сессии (options)
После выполнения скрипта конфигурации происходит ещё ряд скрытых от пользователя процедур: подгрузка объектов рабочего пространства из прошлой сессии, если она была (.RData
); выполнение объявленной в файле конфигурации функции .First()
; подгрузка базовых пакетов (функция base::.First.sys()
), загрузка истории выполненных выражений в предыдущей сессии (R_HISTFILE
или .Rhistory
). Также при выполнении скрипта конфигурации сессии устанавливают опции (options
) сессии.
Как правило, с помощью опций задают правила вычисления и отображения результатов. К наиболее наглядным примерам можно отнести опцию импорта строк как факторов, запрет на отображение чисел в scientific (экспоненциальном) формате или определённый формат десятичного разделителя. Значения по умолчанию выставляются при старте сессии после импорта переменных окружения и скриптов конфигураций при подключении базовых пакетов. При этом можно самостоятельно задать новые значения опций в файле конфигурации до старта сессии или же в скрипте сразу во время работы. Допустимо использовать и консоль, но потом можно легко забыть, что были заданы новые значения, и в дальнейшем долго удивляться результатам.
Полный список опций можно получить с помощью функции options()
, которая отдаёт список названий опций и их значений (значениями могут быть как строковые или числовые параметры, так и объявление функций). Описание опций можно также получить в справке help(options)
. Выведем список пакетов, которые подключаются при старте сессии, помимо base
:
options()$defaultPackages
## [1] "datasets" "utils" "grDevices" "graphics" "stats" "methods"
Многие пакеты в R также имеют свой список опций. При подключении пакетов эти опции становятся видны в общем списке, как правило, с названием пакета в префиксе. Вот, например, какие опции появляются при подключении пакета data.table
:
library(data.table)
options_names <- names(options())
options_names[grep('datatable', options_names)]
## [1] "datatable.alloccol" "datatable.allow.cartesian"
## [3] "datatable.auto.index" "datatable.dfdispatchwarn"
## [5] "datatable.optimize" "datatable.print.class"
## [7] "datatable.print.colnames" "datatable.print.keys"
## [9] "datatable.print.nrows" "datatable.print.rownames"
## [11] "datatable.print.topn" "datatable.print.trunc.cols"
## [13] "datatable.use.index" "datatable.verbose"
## [15] "datatable.warnredundantby"
Значение опции можно получить и с помощью функции getOption()
. Обычно именно этот метод используется, когда надо обратиться к опциям, например, в аргументах функции:
getOption('defaultPackages')
## [1] "datasets" "utils" "grDevices" "graphics" "stats" "methods"
Опции меняются с помощью все той же функции options()
, где аргументом выступает название опции. Изменения в опциях действуют в рамках сессии, поэтому если в работе постоянно требуются какие-то определенные настройки, то есть смысл выносить их в скрипт конфигурации .Rprofile
.
# по умолчанию используется экспоненциальное представление чисел
getOption('scipen')
## [1] 0
print(12345679101112)
## [1] 1.234568e+13
## [1] 999
print(12345679101112)
## [1] 12345679101112
Информация об R-сессии
Очень часто приходится сохранять информацию, на какой машине были произведены те или иные расчёты, какой набор пакетов и их версий использовался. В частности, это очень помогает при расследовании, что пошло не так при выполнении задачи. Получить информацию о сессии можно с помощью функции sessionInfo()
. Функция возвращает объект класса sessionInfo
. При печати объекта выводится сводная информация о сессии: версия ОС и R, используемые библиотеки для линейной алгебры, параметры локали, подключённые пакеты. Формулировка loaded via a namespace (and not attached)
означает, что пакеты подгружены, но пользователь не имеет возможности обращаться к этих пакетам напрямую, в отличие от функций других пакетов.
## R version 4.1.2 (2021-11-01)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 20.04.3 LTS
##
## Matrix products: default
## BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=ru_RU.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=ru_RU.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=ru_RU.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=ru_RU.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] profvis_0.3.7 data.table_1.14.2
##
## loaded via a namespace (and not attached):
## [1] knitr_1.36 xml2_1.3.2 magrittr_2.0.1 downlit_0.2.1
## [5] R6_2.5.1 rlang_0.4.12 fastmap_1.1.0 fansi_0.5.0
## [9] stringr_1.4.0 tools_4.1.2 xfun_0.26 utf8_1.2.2
## [13] jquerylib_0.1.4 htmltools_0.5.2 ellipsis_0.3.2 yaml_2.2.1
## [17] digest_0.6.29 tibble_3.1.6 lifecycle_1.0.1 crayon_1.4.2
## [21] bookdown_0.22.17 htmlwidgets_1.5.4 sass_0.4.0 vctrs_0.3.8
## [25] fs_1.5.0 evaluate_0.14 rmarkdown_2.11 stringi_1.7.6
## [29] compiler_4.1.2 bslib_0.3.1 pillar_1.6.4 jsonlite_1.7.2
## [33] pkgconfig_2.0.3
Объект sessionInfo
содержит более подробную информацию о сессии, в частности, о пакетах: название, имя автора пакета, зависимости, лицензия, версия билда, дата публикации и прочая детальная информация.
# посмотрим информацию о подгруженном пакете Rcpp
si <- sessionInfo()
str(si$loadedOnly$Rcpp)
## NULL