Как узнать, какие пакеты вы использовали в R

У меня очень длинный R script со многими операциями if и исключениями. Как я и собирался, если бы я импортировал и тестировал библиотеки по мере того, как я ушел, и не очень хорошо их документировал. Проблема в том, что если я запустил это из чистой установки, я не уверен, какие операторы будут запускать script, и поэтому какие библиотеки понадобятся.

Мой вопрос: есть ли какая-либо функция R для проверки того, какие библиотеки используются в script?

EDIT: я не использовал все библиотеки, которые были установлены, поэтому print(sessionInfo()) не будет полезен, но я просто хочу запустить script с помощью функции install.packages

Ответ 1

Я не уверен в хорошем способе автоматизировать это... но что вы можете сделать:

  • Откройте новую консоль R
  • Проверьте с sessionInfo, что у вас нет загруженных дополнительных пакетов.
    Вы можете проверить это, используя sessionInfo. Если вы по умолчанию загружаете дополнительные пакеты (например, используя файл .RProfile), я предлагаю вам избежать этого, поскольку это рецепт катастрофы.
    Обычно вы должны загружать только базовые пакеты: stats, graphics, grDevices, utils, datasets, methods и base.

    Вы можете выгрузить любые дополнительные библиотеки, используя:

    detach("package:<packageName>", unload=TRUE)
    
  • Теперь запустите script после комментирования всех вызовов library и require и посмотрите, какие функции выдают ошибку.

  • Чтобы получить какой пакет требуется для каждого типа функции в консоли:

    ??<functionName>
    
  • Загрузите необходимые пакеты и повторите шаги 3-5 до тех пор, пока они не будут удовлетворены.

Ответ 2

Ранее я использовал оболочку script для этого:

#!/usr/bin/env bash

source_files=($(git ls-files '*.R'))
grep -hE '\b(require|library)\([\.a-zA-Z0-9]*\)' "${source_files[@]}" | \
    sed '/^[[:space:]]*#/d' | \
    sed -E 's/.*\(([\.a-zA-Z0-9]*)\).*/\1/' | \
    sort -uf \
    > DEPENDS

Это использует Git для сбора всех R файлов под управлением версиями в проекте. Так как вы все равно должны использовать управление версиями, это, как правило, хорошее решение (хотя вам может понадобиться адаптировать систему контроля версий). Для нескольких случаев, когда проект не находится под управлением версией, вы должны (1) поставить его под контроль версии. Или, если это не так, (2) используйте find . -regex '.*\.[rR]' вместо git ls-files '*.R'.

И он создает DEPENDS файл, содержащий очень простой список зависимостей.

Он находит только прямые вызовы library и require, хотя - если вы завершаете эти вызовы, wont работает script.

Ответ 3

Я нашел list.functions.in.file() из NCmisc (install.packages("NCmisc")) весьма полезной для этого:

list.functions.in.file(filename, alphabetic = TRUE)

Для получения дополнительной информации перейдите по этой ссылке: https://rdrr.io/cran/NCmisc/man/list.functions.in.file.html

Ответ 4

Вы можете посмотреть функцию контрольной точки от Revolution Analytics на GitHub здесь: https://github.com/RevolutionAnalytics/checkpoint

Он делает некоторые из этого и решает проблему воспроизводимости. Но я не вижу, чтобы он мог сообщить список того, что вы используете.

Однако, если вы посмотрели код, вы, вероятно, получите некоторые идеи.

Ответ 5

У меня была аналогичная потребность, когда мне нужно было преобразовать свой код в пакет, поэтому мне нужно определить каждую зависимость пакета и либо импортировать, либо использовать полное имя.

В книге для чтения Extending R я обнаружил, что XRtools::makeImports может сканировать пакет и найти все необходимые пакеты для импорта. Это еще не решает нашу проблему, поскольку оно применимо только к существующему пакету, но оно предоставило основное представление о том, как это сделать.

Я сделал функцию и поместил ее в свой пакет mischelper. Вы можете установить пакет, либо использовать меню добавления RStudio для сканирования текущего файла или выбранного кода, либо использовать функции командной строки. Каждая внешняя функция (fun_inside) и функция, которая ее назвала (использование), будут перечислены в таблице.

введите описание изображения здесь

Теперь вы можете перейти к каждой функции, нажать F1, чтобы найти, какой пакет он принадлежит. У меня на самом деле есть еще один пакет, который может сканировать все установленные пакеты для имен функций и создавать базу данных, но это может вызвать больше ложных срабатываний для этого использования, потому что если вы загружаете только некоторые пакеты, нажав F1, только загрузите пакеты.

Подробнее об использовании на странице моего пакета

https://github.com/dracodoc/mischelper

Ответ 6

На основании ответа каждого человека, особенно eh21 предложению NCmisc пакета, я собрал небольшую функцию, которая выводит список пакетов, используемых во все ваших R сценарии в каталоге, а также их частоту.

library(NCmisc)
library(stringr)
library(dplyr)

checkPacks<-function(path){

    ## get all R files in your directory
    ## by the way, extract R code from Rmd: http://felixfan.github.io/extract-r-code/
    files<-list.files(path)[str_detect(list.files(path), ".R$")]

    ## extract all functions and which package they are from 
    ## using NCmisc::list.functions.in.file
    funs<-unlist(lapply(paste0(path, "/", files), list.functions.in.file))
    packs<-funs %>% names()

    ## "character" functions such as reactive objects in Shiny
    characters<-packs[str_detect(packs, "^character")]

    ## user defined functions in the global environment
    globals<-packs[str_detect(packs, "^.GlobalEnv")]

    ## functions that are in multiple packages' namespaces 
    multipackages<-packs[str_detect(packs, ", ")]

    ## get just the unique package names from multipackages
    mpackages<-multipackages %>%
               str_extract_all(., "[a-zA-Z0-9]+") %>%
               unlist() %>%
               unique()
    mpackages<-mpackages[!mpackages %in% c("c", "package")]

    ## functions that are from single packages
    packages<-packs[str_detect(packs, "package:") & !packs %in% multipackages] %>%
              str_replace(., "[0-9]+$", "") %>%
              str_replace(., "package:", "") 

    ## unique packages
    packages_u<-packages %>%
                unique() %>%
                union(., mpackages)

    return(list(packs=packages_u, tb=table(packages)))

}

checkPacks("~/your/path")