R: Verwenden Sie den Magrittr-Pipe-Operator in einem selbstgeschriebenen Paket

100

Ich möchte %>%den magrittrim Paket eingeführten Pipe-Operator in einem Paket verwenden, das ich selbst geschrieben habe, um dplyrDatentransformationen zu verketten. magrittrist wie Importin der DESCRIPTIONDatei aufgeführt. Nach dem Laden meines eigenen Pakets und dem Testen der Funktion, die den Pipe-Operator verwendet, wird die folgende Fehlermeldung angezeigt:

Fehler im Funktionsnamen (Parameter ,: Funktion "%>%" konnte nicht gefunden werden

Das Ändern %>%in magrittr::%>%im Funktionsquellcode hilft auch nicht, da das Paket nicht mehr erstellt werden kann.

alexander keth
quelle
4
Ich würde vom Rohrbetreiber innerhalb einer Funktion innerhalb eines Pakets abraten. Dies erschwert das Debuggen erheblich (der Aufrufstapel wird mit der Pipe wahnsinnig tief). Bei Paketen habe ich nur eine temporäre Variable überschrieben, was das Testen erheblich erleichtert (denken Sie daran: R sagt Ihnen, in welcher Zeile der Fehler aufgetreten ist). Die Pipe ist für den interaktiven Gebrauch in Ordnung, aber für die Programmierung kann es eine Belastung sein.

Antworten:

99

Es hätte richtig funktionieren sollen, wenn Sie in magrittraufgeführt hätten Depends. Dies wird jedoch nicht empfohlen . Stattdessen lassen Sie magrittrin Importsund fügen die folgende Zeile hinzu NAMESPACE:

importFrom(magrittr,"%>%")

Ich schlage vor, Writing R-Erweiterungen zu lesen . Ihre Frage wird in den Absätzen 1.1.3 und 1.5.1 behandelt.

Tonytonov
quelle
1
@alexanderketh In diesem Fall sollten Sie das grüne Häkchen neben der Antwort drücken, um sie als akzeptiert zu markieren. Willkommen bei SO!
Tonytonov
54
Wenn Sie verwenden roxygen2, können Sie hinzufügen #' importFrom magrittr "%>%", dass NAMESPACE während automatisch gefüllt wird roxygenize().
Roman Luštrik
38
@ RomanLuštrik, nur fehlt @, sollte sein#' @importFrom magrittr "%>%"
Roah
13
Beachten Sie, dass Sie dies nur für die %>%interne Verwendung in Ihrem Paket zulassen . Wenn Ihre API erfordert, dass Benutzer Funktionen mit verketten %>%, müssen sie dennoch explizit laden magrittr. Eine Möglichkeit, dieses Problem zu lösen, besteht darin, die Funktion erneut zu exportieren. Hier ist ein Beispiel dafür.
Ramnath
Dies ist auch, was das usethis-Paket tut, wie hier
jiggunjer
32

Eine zusätzliche Lösung - verwenden Sie das roxygenPaket. Es ist als Teil des devtoolsPakets implementiert . Sobald devtoolsdie Installation installiert ist, devtools::document()wird Ihr Anruf NAMESPACEfür Sie aktualisiert . Außerdem werden automatisch RD-Dateien mit Dokumentation erstellt, was praktisch ist.

Sie fügen einer #' @import packagenameDatei lediglich einen speziellen Kommentar im Format hinzu , um alle Funktionen aus diesem Paket #' @importFrom packagename functionnamezu importieren oder eine Funktion zu importieren. Sie können so viele dieser Kommentare in Ihren Dateien haben, wie Sie möchten, sodass Sie eine Reihe davon oben in jeder Datei oder für jede Ihrer Funktionen haben können, die eine externe Funktion benötigen.

Dann führen Sie es aus devtools::document()und es analysiert Ihren Code nach diesen Kommentaren und erstellt dann eine geeignete NAMESPACEDatei für Sie. Einfach.

Mike Stanley
quelle
1
Wenn ich das mache, werden die folgenden Sauerstoffkommentare durcheinander gebracht, die sich auf die Hilfedatei für die erste Funktion im R-Skript beziehen. Wie trenne ich globale Sauerstoffkommentare von den Hilfedateien?
Jzadra
2
Normalerweise setze ich die Importkommentare für jede Funktion einzeln ein. Auf diese Weise bleiben Ihre Importe korrekt, wenn sich andere Funktionen in der Datei ändern. Dann gibt es also keine globalen Definitionen.
Mike Stanley
31

Es gibt jetzt eine einfachere Möglichkeit, die Pipe in Ihren Paketen zu unterstützen. Das wunderbare Paket usethishat die Funktion use_pipe(). Sie führen diese Funktion einmal aus und sie behandelt alles. So wird die use_pipe()Funktion in der usethisDokumentation beschrieben:

Ist das Setup erforderlich, um die Magrittr-Pipe intern in Ihrem Paket zu verwenden und sie für Benutzer Ihres Pakets erneut zu exportieren:

Fügt Magrittr zu "Importe" in BESCHREIBUNG hinzu

Erstellt R / utils-pipe.R mit der erforderlichen Sauerstoffvorlage

Andrew Brēza
quelle
Fügen Sie die Zeile use_pipe()dem Code hinzu, mit dem Sie das Paket erstellen? Zum Beispiel starte ich : 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). Würde ich nur use_pipe()am Anfang hinzufügen ?
Josh
1
@Josh Sie verwenden die usethisFunktionen einmal, wenn Sie das Paket entwickeln. Diese Funktionen fügen dann die erforderlichen Teile zu den Bauanweisungen und allem anderen hinzu.
Andrew Brēza
18

Angenommen, Sie verwenden RStudio, Hadleys devtoolsPaket, und sind magrittrim Abschnitt "Importe" der DESCRIPTIONDatei aufgeführt. Hier sind die Schritte, die ich unternommen habe, um die %>%Arbeit in meinen Paketfunktionen zu erledigen.

Schreiben Sie zunächst die Funktion 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()
}

Zweitens laufen devtools::document().

Drittens laufen devtools::load_all().

Eine Datei wie diese in Ihrem erstellt wird R/Verzeichnis und Ihre Funktion sollte wie erwartet funktionieren.

Jubelt
quelle
6
Was ist der Zweck von @name %>%hier?
JelenaČuklina