R: użyj operatora potoku magrittr we własnym pakiecie

101

Chciałbym użyć operatora potoku %>%wprowadzonego w magrittrpakiecie w paczce, którą sam napisałem, aby łańcuchowo dplyrprzekształcić dane. magrittrjest wymieniony jako Importw DESCRIPTIONpliku. Po załadowaniu własnego pakietu i przetestowaniu funkcji korzystającej z operatora potoku otrzymuję następujący komunikat o błędzie:

Błąd w functionname (parametr,: nie można znaleźć funkcji "%>%"

Zmiana %>%na magrittr::%>%w kodzie źródłowym funkcji również nie pomaga, ponieważ nie można już zbudować pakietu.

alexander keth
źródło
4
Odradzałbym operatorowi potoku wewnątrz funkcji wewnątrz pakietu. To znacznie utrudnia debugowanie (stos wywołań staje się szalenie głęboki wraz z potokiem). W przypadku pakietów po prostu nadpisałbym zmienną tymczasową, co znacznie ułatwia testowanie (pomyśl: R mówi ci, w której linii wystąpił błąd). Rura nadaje się do użytku interaktywnego, ale w przypadku programowania może być obciążeniem.

Odpowiedzi:

102

Powinno działać poprawnie, jeśli magrittrwpisałeś w Depends. Jednak nie jest to zalecane . Zamiast zostawić magrittrw Importsi dodaj następującą linię NAMESPACE:

importFrom(magrittr,"%>%")

Proponuję czytanie rozszerzeń Pisanie R . Twoje pytanie zostało omówione w punktach 1.1.3 i 1.5.1.

tonytonov
źródło
1
@alexanderketh W takim przypadku należy kliknąć zielony znacznik obok odpowiedzi, aby oznaczyć ją jako zaakceptowaną. Witamy w SO!
tonytonov
54
Jeśli używasz roxygen2, możesz dodać, #' importFrom magrittr "%>%"aby NAMESPACE wypełniło się automatycznie podczas roxygenize().
Roman Luštrik
38
@ RomanLuštrik, po prostu brakuje @, powinno być#' @importFrom magrittr "%>%"
Roah
13
Zwróć uwagę, że pozwoli to na użycie tylko %>%wewnętrznie w pakiecie. Jeśli twoje API wymaga od użytkowników łączenia funkcji przy użyciu %>%, nadal będą musieli jawnie ładować magrittr. Jednym ze sposobów rozwiązania tego problemu jest ponowne wyeksportowanie funkcji. Oto przykład, jak to zrobić.
Ramnath
Tak też działa ten pakiet, jak wspomniano tutaj
jiggunjer
33

Jest teraz łatwiejszy sposób obsługi potoku w pakietach. Wspaniały pakiet usethisma swoją funkcję use_pipe(). Uruchamiasz tę funkcję raz i obsługuje ona wszystko. Oto opis use_pipe()funkcji w usethisdokumentacji:

Czy konfiguracja jest konieczna do wewnętrznego użycia potoku magrittr w pakiecie i ponownego wyeksportowania go dla użytkowników pakietu:

Dodaje magrittr do sekcji „Import” w DESCRIPTION

Tworzy R / utils-pipe.R z niezbędnym szablonem roxygen

Andrew Brēza
źródło
Czy dodajesz wiersz use_pipe()do kodu, którego używasz do tworzenia pakietu? Na przykład, polecenie: 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). Czy dodałbym use_pipe()na początku?
Josh,
1
@Josh, używasz tych usethisfunkcji raz podczas tworzenia pakietu. Te funkcje następnie dodają niezbędne części do instrukcji budowy i wszystkiego innego.
Andrew Brēza,
32

Jedno dodatkowe rozwiązanie - skorzystaj z roxygenpakietu. Jest zaimplementowany jako część devtoolspakietu. Po devtoolszainstalowaniu funkcja dzwonienia devtools::document()zaktualizuje NAMESPACEza Ciebie. Tworzy również automatycznie pliki .Rd z dokumentacją, co jest przydatne.

Wszystko, co musisz zrobić, to dodać specjalny komentarz w formacie #' @import packagenamedo pliku, aby zaimportować wszystkie funkcje z tego pakietu lub #' @importFrom packagename functionnamezaimportować funkcję. Możesz mieć dowolną liczbę tych komentarzy w swoich plikach, więc możesz mieć ich zestaw na początku każdego pliku lub z każdą funkcją wymagającą funkcji zewnętrznej.

Następnie uruchamiasz devtools::document()i analizuje kod w poszukiwaniu tych komentarzy, a następnie tworzy odpowiedni NAMESPACEplik dla Ciebie. Łatwo.

Mike Stanley
źródło
1
Kiedy to robię, miesza następujące komentarze dotyczące tlenu, które odnoszą się do pliku pomocy dla pierwszej funkcji w skrypcie R. Jak oddzielić globalne komentarze dotyczące tlenu od komentarzy w pliku pomocy?
jzadra
2
Zazwyczaj komentarze dotyczące importu umieszczam osobno dla każdej funkcji. Dzięki temu, jeśli inne funkcje w pliku ulegną zmianie, import pozostanie dokładny. Zatem nie ma globalnych definicji.
Mike Stanley
18

Zakładając, że używasz RStudio, devtoolspakietu Hadleya i jest on wymieniony magrittrw sekcji Importy DESCRIPTIONpliku, oto kroki, które podjąłem, aby %>%zadziałać w moich funkcjach pakietu.

Najpierw napisz funkcję 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()
}

Po drugie, biegnij devtools::document().

Po trzecie, biegnij devtools::load_all().

Plik jak to zostanie utworzony w R/katalogu a funkcja powinna działać zgodnie z oczekiwaniami.

Jubbles
źródło
7
jaki jest cel tego @name %>%?
JelenaČuklina