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.