Pertimbangkan tibble di mana setiap kolom adalah vektor karakter yang dapat mengambil banyak nilai - misalkan "A" hingga "F".
library(tidyverse)
sample_df <- tibble(q1 = c("A", "B", "C"), q2 = c("B", "B", "A"))
Saya ingin membuat fungsi yang menggunakan nama kolom sebagai argumen, dan mengode ulang kolom itu sehingga jawaban "A" menjadi NA dan df dikembalikan seperti apa adanya. Alasan untuk mendesainnya dengan cara ini adalah untuk masuk ke dalam pipa yang lebih luas yang melakukan serangkaian operasi menggunakan kolom yang diberikan.
Ada banyak cara untuk melakukan ini. Tapi saya tertarik untuk memahami apa pendekatan tidy_eval / tidyverse idiomatik terbaik. Pertama, nama pertanyaan harus berada di sebelah kiri kata kerja bermutasi, jadi kami menggunakan !!
dan :=
operator dengan tepat. Tapi kemudian, apa yang harus diletakkan di sisi kanan?
fix_question <- function(df, question) {
df %>% mutate(!!question := recode(... something goes here...))
}
fix_question(sample_df, "q1") # should produce a tibble whose first column is (NA, "B", "C")
Pikiran awal saya adalah bahwa ini akan berhasil:
df %>% mutate(!!question := recode(!!question, "A" = NA_character_))
Tapi tentu saja bang-bang di dalam fungsi hanya mengembalikan string karakter literal (mis. "Q1"). Saya akhirnya mengambil apa yang terasa seperti rute peretasan untuk merujuk data di sisi kanan, menggunakan [[
operator base R dan mengandalkan .
konstruk dari dplyr, dan itu berfungsi, jadi dalam beberapa hal saya telah memecahkan masalah mendasar saya:
df %>% mutate(!!question := recode(.[[question]], "A" = NA_character_))
Saya tertarik untuk mendapatkan umpan balik dari orang-orang yang sangat mahir dalam merapikan apakah ada cara yang lebih idiomatis untuk melakukan ini, dengan harapan bahwa melihat contoh yang berhasil akan meningkatkan pemahaman saya tentang fungsi rapi yang ditetapkan secara lebih umum. Adakah pikiran?
q1
(simbol) dan"q1"
(string):df %>% mutate_at( vars(!!ensym(question)), recode, A = NA_character_)
Jawaban:
Di sini, di sisi kanan
:=
, kita dapat menentukansym
untuk mengkonversi ke simbol dan kemudian mengevaluasi (!!
)Pendekatan yang lebih baik yang akan bekerja untuk input yang dikutip dan tidak dikutip
ensym
sumber
Anda dapat menggunakan metode "keriting keriting" sekarang jika Anda memiliki rlang> = 0.4.0 .
Penjelasan terima kasih kepada @ eipi10:
Ini menggabungkan dua langkah proses kutipan-kemudian-tanda kutip menjadi satu langkah, sehingga
{{question}}
setara dengan!!enquo(question)
Perhatikan bahwa tidak seperti
ensym
pendekatan, ini tidak bekerja dengan nama karakter. Lebih buruk lagi, itu melakukan hal yang salah, bukan hanya memberikan kesalahan.sumber
question
pertama-tama harus diubah menjadi quosure (question = enquo(question)
) sebelum digunakan dalam pipa dplyr.{{question}}
setara dengan!!enquo(question)
.Anda dapat membuat fungsi ini sedikit lebih fleksibel dengan memungkinkan vektor nilai yang sudah dikodekan ulang dimasukkan sebagai argumen. Sebagai contoh:
Perhatikan bahwa
recode.vec
"spliced unquote" dengan!!!
. Anda dapat melihat apa yang dilakukan dengan contoh ini, diadaptasi dari Pemrograman dengan sketsa dplyr (cari "splice" untuk melihat contoh yang relevan). Perhatikan bagaimana!!!
"splices" pasangan nilai pengodean ulang ke dalamrecode
fungsi sehingga mereka digunakan sebagai...
argumen direcode
.Jika Anda ingin menjalankan fungsi pengodean ulang pada banyak kolom, Anda dapat mengubahnya menjadi fungsi yang hanya menggunakan nama kolom dan vektor pengodean ulang. Pendekatan ini sepertinya akan lebih ramah pipa.
Atau untuk mengode ulang satu kolom:
sumber