Topik ini membahas verba filter() dari dplyr, yaitu verba yang mengambil sebagian baris tabel berdasarkan kondisi logika. Pembahasan mencakup operator perbandingan dan keanggotaan, penggabungan beberapa kondisi, perilaku nilai NA yang khusus perlu dipahami, fungsi between() untuk kondisi rentang, serta kesalahan yang lazim terjadi. Dataset contoh didefinisikan ulang di awal topik agar seluruh contoh tetap dapat dijalankan ulang secara mandiri.
library(tidyverse)
nilai <- tibble::tibble(
nama = c("Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar", "Gita", "Hana"),
kelas = c("7A", "7B", "7A", "7B", "7A", "7B", "7A", "7B"),
nilai = c(88, 74, 92, 65, 81, 79, 95, 70),
kehadiran = c(0.95, 0.88, 1.00, 0.75, 0.92, 0.85, 0.98, 0.80)
)── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errorsMengambil baris dengan kondisi#
Argumen pertama filter() adalah tabelnya, dan argumen-argumen berikutnya berupa kondisi logika yang dievaluasi pada setiap baris. Kondisi ditulis dengan nama kolom tanpa tanda kutip, dan hasilnya hanya baris-baris yang kondisinya bernilai TRUE. Contoh berikut mengambil seluruh baris siswa kelas 7A.
nilai |> filter(kelas == "7A")# A tibble: 4 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Ali 7A 88 0.95
2 Citra 7A 92 1
3 Eka 7A 81 0.92
4 Gita 7A 95 0.98Tanda == membandingkan kesamaan, sedangkan tanda = tunggal adalah penugasan argumen dan tidak boleh dipakai sebagai pembanding. Kondisi dievaluasi pada seluruh baris sekaligus sebagaimana operasi vektor pada umumnya di R, sehingga satu pemanggilan menguji delapan baris tanpa perulangan eksplisit. Hasilnya selalu berupa tabel baru, sehingga tabel asalnya tetap utuh dan dapat difilter ulang dengan kondisi lain. Operator perbandingan lain bekerja dengan pola yang sama, seperti != untuk ketaksamaan, <, <=, >, dan >= untuk perbandingan besaran.
nilai |> filter(nilai >= 80)# A tibble: 4 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Ali 7A 88 0.95
2 Citra 7A 92 1
3 Eka 7A 81 0.92
4 Gita 7A 95 0.98Apabila yang diuji adalah keanggotaan pada sekumpulan nilai, operator %in% lebih ringkas daripada gabungan pembanding kesamaan. Operator ini menghasilkan TRUE untuk setiap baris yang nilainya terdapat pada vektor di sisi kanannya, dan bernilai FALSE tanpa error apabila nilainya tidak ditemukan.
nilai |> filter(nama %in% c("Ali", "Gita", "Zaki"))# A tibble: 2 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Ali 7A 88 0.95
2 Gita 7A 95 0.98Nama Zaki tidak ada pada tabel, tetapi pemfilteran tetap berjalan dan menghasilkan dua baris yang cocok. Perilaku toleran inilah yang membuat %in% cocok untuk daftar yang isinya mungkin tidak semuanya terdapat pada data.
Menggabungkan beberapa kondisi#
Beberapa kondisi digabungkan dengan operator & untuk dan, | untuk atau, serta ! untuk pembalikan. Pemanggilan filter() dengan beberapa kondisi yang dipisahkan koma mempunyai makna yang sama dengan penggabungan menggunakan &, yaitu seluruh kondisinya harus terpenuhi.
nilai |> filter(kelas == "7A" & nilai >= 90)# A tibble: 2 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Citra 7A 92 1
2 Gita 7A 95 0.98nilai |> filter(kelas == "7A", nilai >= 90)# A tibble: 2 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Citra 7A 92 1
2 Gita 7A 95 0.98Kedua pemanggilan di atas menghasilkan tabel yang sama persis. Operator | mengambil baris yang memenuhi salah satu kondisinya, sehingga jumlah baris hasilnya biasanya lebih banyak daripada penggabungan dengan &. Apabila kondisi & dan | bercampur dalam satu ekspresi, operator & dievaluasi lebih dahulu menurut presedensinya, sehingga tanda kurung perlu dipakai secara eksplisit apabila maksud pengelompokannya berbeda.
nilai |> filter(nilai >= 90 | kehadiran < 0.8)# A tibble: 3 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Citra 7A 92 1
2 Dewi 7B 65 0.75
3 Gita 7A 95 0.98Pembalikan dengan ! membalik nilai kondisi, sehingga !(kelas == "7A") mengambil seluruh baris yang bukan kelas 7A. Hasil yang sama diperoleh dengan kelas != "7A", dan pilihan di antara keduanya diserahkan pada keterbacaan.
nilai |> filter(!(kelas == "7A"))# A tibble: 4 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Budi 7B 74 0.88
2 Dewi 7B 65 0.75
3 Fajar 7B 79 0.85
4 Hana 7B 70 0.8 Perilaku NA dalam filter#
Kondisi yang melibatkan nilai NA tidak menghasilkan TRUE maupun FALSE, melainkan NA, karena perbandingan dengan nilai yang tidak diketahui tidak dapat dipastikan. Verba filter() hanya menyimpan baris yang kondisinya TRUE, sehingga baris yang kondisinya NA ikut terbuang tanpa pesan apa pun. Perilaku ini berakar pada logika tiga nilai R, yaitu TRUE, FALSE, dan NA sebagai perwakilan nilai yang tidak diketahui. Perbandingan apa pun yang melibatkan NA tidak dapat dipastikan jawabannya, sehingga hasilnya kembali NA dan bukan FALSE. Perilaku ini perlu dikenali karena hasil filter bisa kehilangan baris secara diam-diam. Tabel kecil berikut dipakai untuk memperlihatkannya, dengan satu skor yang belum tersedia.
ulangan <- tibble::tibble(
nama = c("Ali", "Budi", "Citra"),
skor = c(88, NA, 75)
)
ulangan |> filter(skor >= 80)# A tibble: 1 × 2
nama skor
<chr> <dbl>
1 Ali 88Hasilnya hanya memuat Ali. Baris Citra terbuang karena skornya 75 tidak memenuhi kondisi, sedangkan baris Budi yang skornya NA ikut terbuang tanpa pesan. Apabila baris bernilai NA memang ingin ditemukan, fungsi is.na() menguji keberadaan nilai NA dan menghasilkan TRUE untuk baris yang menyimpannya.
ulangan |> filter(is.na(skor))# A tibble: 1 × 2
nama skor
<chr> <dbl>
1 Budi NACara menyertakan kembali baris bernilai NA adalah menambahkannya sebagai kondisi tersendiri pada penggabungan.
ulangan |> filter(skor >= 80 | is.na(skor))# A tibble: 2 × 2
nama skor
<chr> <dbl>
1 Ali 88
2 Budi NARentang nilai dengan between()#
Kondisi rentang semacam nilai >= 74 & nilai <= 88 dapat ditulis lebih ringkas dengan fungsi between(). Fungsi ini menerima tiga argumen, yaitu kolom yang diuji, batas bawah, dan batas atas, dan kedua batasnya bersifat inklusif.
nilai |> filter(between(nilai, 74, 88))# A tibble: 4 × 4
nama kelas nilai kehadiran
<chr> <chr> <dbl> <dbl>
1 Ali 7A 88 0.95
2 Budi 7B 74 0.88
3 Eka 7A 81 0.92
4 Fajar 7B 79 0.85Hasilnya memuat nilai 74 dan 88 yang menempel pada kedua batas, beserta 79 dan 81 yang berada di antaranya. between() tidak menambah kemampuan baru karena hasilnya identik dengan penggabungan dua perbandingan, tetapi menyatakan maksud rentang secara eksplisit sehingga kondisi lebih mudah dibaca.
Kesalahan umum#
Kesalahan yang paling sering adalah memakai tanda = sebagai pembanding, padahal tanda yang benar adalah ==.
nilai |> filter(kelas = "7A")Error in filter(nilai, kelas = "7A") : We detected a named input.
ℹ This usually means that you've used `=` instead of `==`.
ℹ Did you mean `kelas == "7A"`?Pesan We detected a named input menandakan R menafsirkan kelas = "7A" sebagai pemberian argumen bernama, bukan perbandingan, dan pesannya bahkan menyertakan saran perbaikan yang berbunyi Did you mean .... Kesalahan kedua yang lazim adalah lupa bahwa NA tidak pernah lolos perbandingan, sebagaimana dijelaskan pada bagian sebelumnya, sehingga baris hilang tanpa pesan dan hasil analisis ternyata lebih sedikit daripada yang diperkirakan.
Ringkasan#
filter()menyimpan baris yang kondisinya TRUE, dengan kondisi yang ditulis memakai nama kolom tanpa tanda kutip.- Perbandingan memakai
==,!=,<,<=,>,>=, keanggotaan memakai%in%, dan penggabungan kondisi memakai&,|, serta!. - Kondisi yang dipisahkan koma berarti penggabungan dengan
&. - Perbandingan dengan NA menghasilkan NA, sehingga baris tersebut terbuang tanpa pesan, dan
is.na()dipakai untuk mendeteksi atau menyertakannya. between(kolom, bawah, atas)menuliskan kondisi rentang inklusif secara ringkas, sedangkan tanda=sebagai pembanding menghasilkan error.
Referensi#
- dplyr: A Grammar of Data Manipulation — tidyverse
— dokumentasi resmi
filter()beserta aturan kondisi logika dan penanganan NA-nya. - R for Data Science, edisi ke-2 — Wickham, Çetinkaya-Rundel, Grolemund — bab transformasi data membahas filter, operator logika, dan keunikan nilai NA.