Какой самый простой подход к файлам R с интервалом между именами с помощью `file::function`

#r #package #setup-project

#r #пакет #настройка-проект

Вопрос:

Критерии для ответа на этот вопрос

Учитывая следующую функцию (в своем собственном скрипте)

 # something.R
hello <- function(x){
    paste0("hello ", x)
}
  

Какова самая минимальная настройка, которая позволит следующее

 library(something)
x <- something::hello('Sue')
# x now has value: "hello Sue"
  

Контекст

В Python очень просто иметь каталог, содержащий некоторый код, и использовать его как

 # here foo is a directory
from foo import bar
bar( ... ) 
  

Хотя я не уверен, как сделать что-то подобное в R.

Я знаю, что есть source(file.R) , но это помещает все в глобальное пространство имен. Я также знаю, что есть library(package) который предоставляет package::function . В чем я не уверен, так это в том, существует ли простой подход к использованию этого пространства имен в R. Руководства по упаковке, которые я искал, кажутся довольно сложными (по сравнению с Python).

Комментарии:

1. @бакс; sys.source("something.R", envir = something<-new.env()); something$hello("Sue")

2. @user20650 Меня интересовал минимальный объем кода, необходимый для использования script::function() синтаксиса, и я все еще хотел бы это увидеть. Тем не менее, sys.source это определенно полезно и, вероятно, решает для меня насущную проблему, спасибо.

3. Либо вы отправляете файл с помощью source(), либо создаете пакет. Вы не импортируете файлы и пространства имен в R. Но создать пакет несложно, и на самом деле не стоит пытаться обойти его.

4. Если я правильно понимаю — создать пакет легко, но слишком многословно, чтобы вставить в ответ stackoverflow

5. Вы думаете, что это излишне, потому что вы этого не пробовали, но я уверяю вас, что ваш пакет с указанной выше функцией занимает 40 секунд работы

Ответ №1:

Я не знаю, есть ли реальная выгода в создании пространства имен только для одной быстрой функции. Это просто не так, как должно быть (я думаю).

Но в любом случае вот довольно минималистичное решение:

Сначала установите один раз: install.packages("namespace")

Функция, которую вы хотели вызвать в пространстве имен:

 hello <- function(x){
  paste0("hello ", x)
}
  

Создание вашего пространства имен, назначение функции и экспорт

 ns <- namespace::makeNamespace("newspace")
assign("hello",hello ,env = ns)
base::namespaceExport(ns, ls(ns))
  

Теперь вы можете вызывать свою функцию с вашим новым пространством имен

 newspace::hello("you")
  

Ответ №2:

Вот самый быстрый рабочий процесс, который я знаю, для создания пакета с использованием RStudio. Пакет по умолчанию уже содержит hello функцию, которую я переписал вашим кодом.

Обратите внимание, что там также было поле «создать пакет на основе исходных файлов», которое я не использовал, но вы могли бы.

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

Пакет, выполненный таким образом, будет содержать экспортированные недокументированные непроверенные функции.

Если вы хотите узнать, как документировать, экспортировать или нет, писать тесты и запускать проверки, включать другие объекты, кроме функций, включать скомпилированный код, делиться на github, делиться на CRAN.. Эта книга описывает рабочий процесс, используемый тысячами пользователей, и разработана таким образом, что вы обычно можете читать разделы независимо.


Если вы не хотите делать это из графического интерфейса, вы можете использовать utils::package.skeleton() для создания папки пакета и remotes::install_local() для его установки :

Воспроизводимая настройка

 # create a file containing function definition

# where your current function is located
function_path <- tempfile(fileext = ".R")
cat('
hello <- function(x){
  paste0("hello ", x)
}
', file = function_path)

# where you store your package code
package_path <- tempdir()
  

Решение :

 # create package directory at given location
package.skeleton("something", code_file = file_path, path = package_path)
# remove sample doc to make remotes::install_local happy
unlink(file.path(package_path, "something", "man/"), TRUE) 
# install package
remotes::install_local(file.path(package_path, "something"))