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.


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.


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


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.


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.


7
jaki jest cel tego @name %>%?
— JelenaČuklina
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.