R: gunakan operator pipa magrittr dalam paket yang ditulis sendiri

101

Saya ingin menggunakan operator pipa yang %>%diperkenalkan dalam magrittrpaket dalam paket yang saya tulis sendiri untuk dplyrtransformasi data berantai . magrittrterdaftar seperti Importpada DESCRIPTIONfile. Setelah memuat paket saya sendiri dan menguji fungsi yang menggunakan operator pipa, saya mendapatkan pesan kesalahan berikut:

Kesalahan dalam nama fungsi (parameter,: tidak dapat menemukan fungsi "%>%"

Mengubah %>%ke magrittr::%>%dalam kode sumber fungsi juga tidak membantu karena paket tersebut tidak dapat dibuat lagi.

alexander keth
sumber
4
Saya akan menyarankan agar operator pipa di dalam fungsi di dalam paket. Itu membuat debugging jauh lebih sulit (tumpukan panggilan menjadi sangat dalam dengan pipa). Untuk paket, saya baru saja menimpa variabel sementara, yang membuat pengujian jauh lebih mudah (pikirkan: R memberi tahu Anda di baris mana kesalahan terjadi). Pipa itu bagus untuk penggunaan interaktif tetapi untuk pemrograman itu bisa menjadi beban.

Jawaban:

101

Seharusnya berfungsi dengan benar jika Anda telah magrittrmendaftar di Depends. Namun, hal ini tidak disarankan . Sebaliknya, Anda meninggalkan magrittrdi Importsdan tambahkan baris berikut ke NAMESPACE:

importFrom(magrittr,"%>%")

Saya sarankan membaca ekstensi Menulis R . Pertanyaan Anda tercakup dalam paragraf 1.1.3 dan 1.5.1.

tonytonov
sumber
1
@alexanderketh Dalam hal ini Anda harus menekan tanda centang hijau di sebelah jawaban untuk menandainya sebagai diterima. Selamat datang di SO!
tonytonov
54
Jika Anda menggunakan roxygen2, Anda dapat menambahkan #' importFrom magrittr "%>%"agar NAMESPACE terisi secara otomatis selama roxygenize().
Roman Luštrik
38
@ RomanLuštrik, hanya hilang @, seharusnya#' @importFrom magrittr "%>%"
Roah
13
Perhatikan bahwa ini hanya akan memungkinkan Anda untuk menggunakan secara %>%internal dalam paket Anda. Jika API Anda mengharuskan pengguna untuk merangkai fungsi menggunakan %>%, mereka masih harus memuat secara eksplisit magrittr. Salah satu cara untuk mengatasi masalah ini adalah mengekspor ulang fungsinya. Berikut ini contoh cara melakukannya.
Ramnath
Ini juga yang dilakukan oleh paket ini menggunakan, seperti yang disebutkan di sini
jiggunjer
33

Sekarang ada cara yang lebih mudah untuk mendukung pipa di paket Anda. Paket yang luar biasa usethismemiliki fungsinya use_pipe(). Anda menjalankan fungsi itu sekali dan itu menangani semuanya. Beginilah use_pipe()fungsi dijelaskan dalam usethisdokumentasi:

Apakah pengaturan diperlukan untuk menggunakan pipa magrittr secara internal dalam paket Anda dan untuk mengekspor ulang untuk pengguna paket Anda:

Menambahkan magrittr ke "Impor" di DESCRIPTION

Membuat R / utils-pipe.R dengan template roxygen yang diperlukan

Andrew Brēza
sumber
Apakah Anda menambahkan baris use_pipe()ke kode yang Anda gunakan untuk membuat paket? Sebagai contoh, saya menjalankan: 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). Apakah saya akan menambahkan use_pipe()di awal?
Josh
1
@Josh Anda menggunakan usethisfungsi satu kali saat Anda mengembangkan paket. Fungsi-fungsi tersebut kemudian menambahkan bagian yang diperlukan ke instruksi build dan yang lainnya.
Andrew Brēza
32

Satu solusi tambahan - gunakan roxygenpaketnya. Ini diimplementasikan sebagai bagian dari devtoolspaket. Setelah devtoolsdipasang, panggilan devtools::document()akan memperbarui fileNAMESPACE untuk Anda. Itu juga secara otomatis membangun file .Rd dengan dokumentasi, yang berguna.

Yang Anda lakukan hanyalah menambahkan komentar khusus dalam format #' @import packagenameke file untuk mengimpor semua fungsi dari paket itu, atau#' @importFrom packagename functionname untuk mengimpor fungsi. Anda dapat memiliki komentar ini sebanyak yang Anda inginkan di file Anda, sehingga Anda dapat memiliki satu set komentar di bagian atas setiap file, atau dengan setiap fungsi Anda yang memerlukan fungsi eksternal.

Kemudian Anda menjalankan devtools::document()dan mem-parsing kode Anda mencari komentar tersebut, dan kemudian membuat NAMESPACEfile yang sesuai untuk Anda. Mudah.

Mike Stanley
sumber
1
Ketika saya melakukan ini, itu mengacaukan komentar oksigen berikut yang berkaitan dengan file bantuan untuk fungsi pertama dalam skrip R. Bagaimana cara memisahkan komentar oksigen global dari yang file bantuan?
jzadra
2
Saya biasanya meletakkan komentar impor dengan masing-masing fungsi secara individual. Dengan begitu, jika fungsi lain dalam file berubah, impor Anda tetap akurat. Jadi tidak ada definisi global.
Mike Stanley
18

Dengan asumsi Anda menggunakan RStudio, devtoolspaket Hadley , dan terdaftar magrittrdi bagian Impor DESCRIPTIONfile, berikut adalah langkah-langkah yang saya lakukan untuk membuatnya.%>% fungsi paket saya berfungsi.

Pertama, tulis fungsi 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()
}

Kedua, lari devtools::document() .

Ketiga, lari devtools::load_all().

File seperti ini akan dibuat di R/direktori Anda dan fungsi Anda akan berfungsi seperti yang diharapkan.

Jubbles
sumber
6
apa tujuan @name %>%disini?
JelenaČuklina