R: використовуйте магнітр трубопровідника в самостійно написаному пакеті


101

Мені б хотілося використовувати оператор pipe, що %>%вводиться в magrittrкомплекті, в пакеті, який я написав сам для ланцюгових dplyrперетворень даних. magrittrвказано як Importу DESCRIPTIONфайлі. Після завантаження власного пакету та тестування функції, яка використовує оператор pipe, я отримую таке повідомлення про помилку:

Помилка в імені функції (параметр:: не вдалося знайти функцію "%>%"

Зміна %>%до magrittr::%>%у вихідному коді функції не допомагає , тому що пакет не може бути побудовано більше.


4
Я би радив проти оператора труби всередині функції, яка знаходиться всередині пакета. Це робить налагодження набагато складніше (стек викликів стає шалено глибоким з трубою). Для пакетів я просто перезаписав тимчасову змінну, що полегшує тестування (подумайте: R повідомляє вам, у якому рядку сталася помилка). Труба чудово підходить для інтерактивного використання, але для програмування це може бути тягарем.

Відповіді:


101

Він мав би справно працювати, якби ви magrittrвказали його Depends. Однак це не радиться . Замість цього, ви залишаєте magrittrв Importsі додайте наступний рядок NAMESPACE:

importFrom(magrittr,"%>%")

Я пропоную читати розширення Написання R . Ваше запитання розкрито в пунктах 1.1.3 та 1.5.1.


1
@alexanderketh У такому випадку слід натиснути зелену галочку біля відповіді, щоб позначити її як прийняту. Ласкаво просимо до SO!
tonytonov

54
Якщо ви користуєтесь roxygen2, ви можете додати, #' importFrom magrittr "%>%"щоб NAMESPACE автоматично заповнювався протягом roxygenize().
Роман Луштрик

38
@ RomanLuštrik, щойно відсутній @, має бути#' @importFrom magrittr "%>%"
Roah

13
Зауважте, що це дозволить вам використовувати лише %>%внутрішньо у вашому пакеті. Якщо ваш API вимагає від користувачів ланцюжкових функцій %>%, вони все одно повинні буде явно завантажуватися magrittr. Один із способів вирішити цю проблему - реекспорт функції. Ось приклад того, як це зробити.
Рамнат

Це також робить цей пакунок, як згадується тут
jiggunjer

33

Зараз є простіший спосіб підтримати трубу у ваших пакунках. Чудовий пакет usethisмає функцію use_pipe(). Ви запускаєте цю функцію один раз, і вона обробляє все. Ось як use_pipe()описана функція в usethisдокументації:

Чи потрібна настройка, щоб використовувати трубу магнітрів внутрішньо у вашому пакеті та реекспортувати її для користувачів вашого пакету:

Додано magrittr до "Імпортувати" в ОПИС

Створює R / utils-pipe.R з необхідним шаблоном roxygen


Ви додаєте рядок use_pipe()до коду, який ви використовуєте для створення пакету? Наприклад, я біжу: usethis::use_description(usethis_description); usethis::use_build_ignore(directories); usethis::use_build_ignore(paste0(pkg_name, ".Rproj")); if (file.exists(file.path(pkg_path, "NAMESPACE"))) { file.remove(file.path(pkg_path, "NAMESPACE")) }; devtools::document(pkg_path); devtools::check(pkg_path); devtools::load_all(pkg_path); devtools::install(pkg_path). Я б просто додати use_pipe()на початку?
Джош

1
@Josh ви використовуєте usethisфункції один раз, коли розробляєте пакет. Потім ці функції додають необхідні частини до інструкцій зі збирання та всього іншого.
Андрій Бреза

32

Ще одне додаткове рішення - використовувати roxygenпакет. Він реалізований як частина devtoolsпакету. Після devtoolsвстановлення виклик devtools::document()оновить NAMESPACEдля вас. Він також автоматично створює .Rd файли з документацією, що зручно.

Все, що вам потрібно зробити - це додати спеціальний коментар у форматі #' @import packagenameдо файлу, щоб імпортувати всі функції з цього пакету, або#' @importFrom packagename functionname імпортувати функцію. Ви можете мати стільки цих коментарів, скільки хочете у своїх файлах, так що ви можете мати їх набір у верхній частині кожного файлу або з кожною з своїх функцій, яка потребує зовнішньої функції.

Потім ви запускаєте, devtools::document()і він аналізує ваш код, шукаючи ці коментарі, і тоді він створює відповідний NAMESPACEфайл для вас. Легко.


1
Коли я це роблю, він заплутує наступні коментарі кисню, які стосуються файлу довідки для першої функції в сценарії R. Як я відокремлюю глобальні коментарі кисню від файлів довідки?
jzadra

2
Зазвичай я ставлю коментарі до імпорту з кожною функцією окремо. Таким чином, якщо інші функції у файлі змінюються, імпорт залишається точним. Тож глобальних визначень немає.
Майк Стенлі

18

Якщо припустити, що ви використовуєте RStudio, devtoolsпакунок Хедлі та вказані magrittrу розділі Імпорт DESCRIPTIONфайлу, ось кроки, які я вжив, щоб зробити %>%роботу у своїх функціях (пакунках) пакунків.

По-перше, функція запису foo.R:

#' Convert \code{data.frame} to \code{list}.
#' 
#' @importFrom magrittr %>%
#' @name %>%
#' @rdname pipe
#' @export
#' @param x A \code{data.frame} object.
#' @examples
#' my_result <- foo(iris)
#'
foo <- function(x) {
    x %>%
        as.list()
}

По-друге, біжи devtools::document() .

По-третє, біжи devtools::load_all().

У вашому каталозі буде створений такий файл, R/і ваша функція повинна працювати так, як очікувалося.


6
яка тут мета @name %>%?
JelenaČuklina
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.