R: usa l'operatore magrittr pipe nel pacchetto scritto da te


101

Vorrei utilizzare l'operatore pipe %>%introdotto nel magrittrpacchetto in un pacchetto che ho scritto io stesso per concatenare dplyrle trasformazioni dei dati. magrittrè elencato come Importnel DESCRIPTIONfile. Dopo aver caricato il mio pacchetto e testato la funzione che utilizza l'operatore pipe, ricevo il seguente messaggio di errore:

Errore nel nome funzione (parametro:: impossibile trovare la funzione "%>%"

Anche il passaggio %>%a magrittr::%>%nel codice sorgente della funzione non aiuta perché il pacchetto non può più essere compilato.


4
Vorrei sconsigliare l'operatore pipe all'interno di una funzione all'interno di un pacchetto. Rende il debug molto più difficile (lo stack di chiamate diventa follemente profondo con la pipe). Per i pacchetti sovrascriverei semplicemente una variabile temporanea, il che rende i test molto più semplici (pensa: R che ti dice su quale riga si è verificato l'errore). Il tubo va bene per l'uso interattivo ma per la programmazione può essere un peso.

Risposte:


101

Avrebbe dovuto funzionare correttamente se tu fossi stato magrittrelencato in Depends. Tuttavia, questo non è consigliato . Invece, si lascia magrittrin Importse aggiungere la seguente riga a NAMESPACE:

importFrom(magrittr,"%>%")

Suggerisco di leggere le estensioni di scrittura R . La tua domanda è trattata nei paragrafi 1.1.3 e 1.5.1.


1
@alexanderketh In tal caso dovresti premere il segno di spunta verde accanto alla risposta per contrassegnarla come accettata. Benvenuto in SO!
tonytonov

54
Se stai utilizzando roxygen2, potresti aggiungere #' importFrom magrittr "%>%"per avere NAMESPACE popolato automaticamente durante roxygenize().
Roman Luštrik

38
@ RomanLuštrik, manca solo @, dovrebbe essere#' @importFrom magrittr "%>%"
Roah

13
Nota che questo ti permetterà solo di usare %>%internamente nel tuo pacchetto. Se l'API richiede agli utenti di concatenare le funzioni utilizzando %>%, dovranno comunque caricare in modo esplicito magrittr. Un modo per risolvere questo problema è riesportare la funzione. Ecco un esempio di come farlo.
Ramnath

Questo è anche ciò che fa l'uso di questo pacchetto, come menzionato qui
jiggunjer

33

Ora c'è un modo più semplice per supportare il pipe nei tuoi pacchetti. Il meraviglioso pacchetto usethisha la funzione use_pipe(). Esegui quella funzione una volta e gestisce tutto. Ecco come use_pipe()viene descritta la funzione nella usethisdocumentazione:

Il setup è necessario per usare il pipe di magrittr internamente nel tuo pacchetto e per riesportarlo per gli utenti del tuo pacchetto:

Aggiunge magrittr a "Imports" in DESCRIPTION

Crea R / utils-pipe.R con il modello roxygen necessario


Aggiungete la riga use_pipe()al codice che usate per costruire il pacchetto? Per esempio, ho eseguito: 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). Vorrei solo aggiungere use_pipe()all'inizio?
Josh

1
@ Josh usi le usethisfunzioni una volta durante lo sviluppo del pacchetto. Queste funzioni aggiungono quindi le parti necessarie alle istruzioni di costruzione e tutto il resto.
Andrew Brēza

32

Una soluzione aggiuntiva: usa il roxygenpacchetto. È implementato come parte del devtoolspacchetto. Una volta devtoolsinstallato, la chiamata devtools::document()aggiornerà il tuo NAMESPACEper te. Inoltre, crea automaticamente i file .Rd con la documentazione, il che è utile.

Tutto quello che devi fare è aggiungere un commento speciale nel formato #' @import packagenamea un file per importare tutte le funzioni da quel pacchetto o #' @importFrom packagename functionnameper importare una funzione. Puoi avere tutti i commenti che desideri nei tuoi file, quindi puoi averne un insieme all'inizio di ogni file o con ciascuna delle tue funzioni che necessita di una funzione esterna.

Quindi esegui devtools::document()e analizza il tuo codice alla ricerca di quei commenti, quindi crea un NAMESPACEfile appropriato per te. Facile.


1
Quando lo faccio, incasina i seguenti commenti sull'ossigeno che riguardano il file della guida per la prima funzione nello script R. Come separo i commenti globali sull'ossigeno da quelli del file della guida?
jzadra

2
Di solito metto singolarmente i commenti di importazione con ciascuna funzione. In questo modo, se altre funzioni nel file cambiano, le tue importazioni rimangono accurate. Quindi non ci sono definizioni globali.
Mike Stanley

18

Supponendo che tu stia utilizzando RStudio, il devtoolspacchetto di Hadley ed elencato magrittrnella sezione Imports del DESCRIPTIONfile, ecco i passaggi che ho seguito per %>%lavorare nelle funzioni del mio pacchetto.

Innanzitutto, scrivi la funzione 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()
}

Secondo, corri devtools::document().

Terzo, corri devtools::load_all().

Un file come questo verrà creato nella tua R/directory e la tua funzione dovrebbe funzionare come previsto.


6
qual è lo scopo di @name %>%qui?
JelenaČuklina
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.