Ketika saya perlu memfilter data.frame, yaitu, mengekstrak baris yang memenuhi kondisi tertentu, saya lebih suka menggunakan subset
fungsi:
subset(airquality, Month == 8 & Temp > 90)
Alih-alih [
fungsi:
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
Ada dua alasan utama untuk preferensi saya:
Saya menemukan kode membaca lebih baik, dari kiri ke kanan. Bahkan orang yang tidak tahu apa-apa tentang R bisa mengatakan apa yang dilakukan
subset
pernyataan di atas.Karena kolom dapat disebut sebagai variabel dalam
select
ekspresi, saya dapat menyimpan beberapa penekanan tombol. Dalam contoh saya di atas, saya hanya perlu mengetikairquality
satu kalisubset
, tetapi tiga kali dengan[
.
Jadi saya hidup bahagia, menggunakan subset
mana mana karena lebih pendek dan membaca lebih baik, bahkan menganjurkan keindahannya kepada sesama R coders saya. Tapi kemarin duniaku pecah. Saat membaca subset
dokumentasi, saya perhatikan bagian ini:
Peringatan
Ini adalah fungsi kenyamanan yang dimaksudkan untuk digunakan secara interaktif. Untuk pemrograman, lebih baik menggunakan fungsi standar subsetting seperti [, dan khususnya evaluasi subset argumen non-standar dapat memiliki konsekuensi yang tidak terduga.
Bisakah seseorang membantu menjelaskan apa yang dimaksud penulis?
Pertama, apa yang mereka maksud dengan " untuk digunakan secara interaktif "? Saya tahu apa sesi interaktif itu, sebagai lawan dari skrip dijalankan dalam mode BATCH tapi saya tidak melihat perbedaan apa yang harus dibuat.
Lalu, bisakah Anda menjelaskan " evaluasi non-standar dari subset argumen " dan mengapa itu berbahaya, mungkin memberikan contoh?
with(airquality, airquality[Month == 8 & Temp > 90, ])
dplyr::filter
memiliki masalah yang sama. Yaitu jika lingkungan kebetulan memiliki variabel dengan nama itu, ia akan menggunakannya sebagai ganti variabel dalam bingkai data. Membuat debugging membingungkan!Jawaban:
Pertanyaan ini dijawab dengan baik di komentar oleh @James, menunjuk pada penjelasan yang sangat baik dari Hadley Wickham tentang bahaya
subset
(dan fungsi-fungsi seperti itu) [di sini] . Baca itu!Ini agak lama dibaca, jadi mungkin berguna untuk mencatat di sini contoh yang digunakan Hadley yang paling langsung menjawab pertanyaan "apa yang bisa salah?":
Hadley menyarankan contoh berikut: misalkan kita ingin mengatur ulang dan kemudian menyusun ulang bingkai data menggunakan fungsi berikut:
Ini mengembalikan kesalahan:
karena R tidak lagi "tahu" di mana menemukan objek yang disebut 'cyl'. Dia juga menunjukkan hal-hal aneh yang dapat terjadi jika secara kebetulan ada objek yang disebut 'cyl' di lingkungan global:
(Jalankan mereka dan lihat sendiri, ini cukup gila.)
sumber
subset(mtcars, cyl == 4)
(di tingkat atas), di mana R mencari cyl? Jika melihat kemtcars
objek yang diteruskan kesubset()
, maka bukankah seharusnya ia dapat menemukancyl
bahkan jikascramble
berada dalam fungsi lain, karenamtcars
masih diteruskan ke sana? Jika pertanyaan saya tidak masuk akal, Anda bisa menguraikan lebih lanjut mengapa R tidak bisa lagi ditemukancyl
. Terima kasih!subset.data.frame
, hal yang kami coba evaluasi pada saat itu adalah adilcondition
. Itu tidak ada dimtcars
. Jadisubset.data.frame
digunakanenclos = parent.frame()
untuk memastikan bahwacondition
dievaluasi dengan benar sebagaicyl == 4
. Tapi kemudian kita telah muncul kembali ke bingkai terlampir, dan sekarang ketika R mencaricyl
itu tidak lagi melihat ke dalammtcars
. Jika kami tidak menggunakanenclos
, sesuatu sepertisubset(mtcars,cyl == a)
tidak akan berfungsi sama sekali.subset.data.frame
adalahx[r, vars, drop = drop]
. Masalahnya adalah bagaimana mendapatkan dari tanda kutipsubset
danselect
argumen untuk sesuatu yang dapat Anda sampaikan secara sah[.data.frame
.[]
?Juga
[
lebih cepat:sumber
subset
tidak seperti[
menghilangkan baris tempat filter mengevaluasiNA
. Lakukan ini dan Anda akan melihat bahwa keduanya sama-sama cepat bila dibandingkan "cukup":x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })