Cara Mengganti Nilai yang Hilang (NA) di R: na.omit & na.rm
โก Ringkasan Cerdas
Panduan Mengganti Nilai yang Hilang di R membahas cara mendeteksi nilai NA, menghapus baris yang tidak lengkap dengan na.omit(), dan mengisinya dengan nilai rata-rata atau median melalui mutate(). Panduan ini menggunakan dataset Titanic, di mana usia dan tarif sama-sama memiliki pengamatan yang hilang.

Apa itu nilai yang hilang (missing values) di R?
Nilai yang hilang muncul ketika suatu observasi tidak memiliki nilai yang tercatat dalam sebuah kolom, atau ketika placeholder non-numerik berada di tempat seharusnya ada angka. Nilai yang hilang harus dihapus atau diganti sebelum perhitungan apa pun, karena sebagian besar fungsi R mengembalikan NA begitu nilai tersebut ada.
Tutorial ini menunjukkan cara menangani nilai yang hilang dengan pustaka dplyr, bagian dari ekosistem tidyverse untuk analisis data.
Langkah pertama selalu mencari tahu berapa banyak nilai yang hilang dan di mana letaknya.
Cara Mendeteksi dan Menghitung Nilai yang Hilang di R
Sebelum memutuskan apa yang harus dilakukan terhadap nilai yang hilang, Anda perlu mengetahui berapa banyak nilai yang hilang dan di mana letaknya. R menawarkan empat cara pengecekan, mulai dari jawaban ya atau tidak tunggal hingga penghitungan lengkap per kolom.
# 1. Is there any NA at all? anyNA(df_titanic) # 2. How many in total? sum(is.na(df_titanic)) # 3. How many per column, the most useful view colSums(is.na(df_titanic)) # 4. Percentage missing per column round(colMeans(is.na(df_titanic)) * 100, 1)
Dalam praktiknya, colSums() adalah fungsi yang tepat untuk digunakan. Fungsi ini mengembalikan vektor bernama dengan satu hitungan per kolom, yang langsung menunjukkan apakah suatu variabel kehilangan sejumlah nilai atau sebagian besar kosong.
Menghitung baris lengkap. complete.cases() mengembalikan TRUE untuk baris yang tidak memiliki nilai yang hilang di mana pun, yang memberi tahu Anda sebelumnya berapa banyak data yang akan dibuang oleh na.omit():
sum(complete.cases(df_titanic)) # rows that would survive sum(!complete.cases(df_titanic)) # rows that would be dropped
Peringatan tentang placeholder. R hanya mengenali NA. Dataset sering kali mengkodekan nilai yang hilang sebagai string kosong, spasi, โN/Aโ, โ-โ, atau angka sentinel seperti -99 atau 999. Nilai-nilai tersebut lolos dari semua pemeriksaan di atas tanpa terdeteksi. Konversikan nilai-nilai tersebut saat impor agar alur kerja selanjutnya berfungsi dengan baik:
df <- read.csv(PATH, na.strings = c("", " ", "NA", "N/A", "-", "-99"))
Selalu periksa rentang setiap kolom numerik setelah impor. Usia -99 atau tarif 9999 jauh lebih berbahaya daripada NA yang sebenarnya, karena tidak ada fungsi yang akan memperingatkan Anda tentang hal itu.
Jenis Data yang Hilang: MCAR, MAR, dan MNAR
Alasan mengapa suatu nilai hilang menentukan apakah pengisian nilai tersebut aman dilakukan. Para ahli statistik mengenali tiga mekanisme.
- MCAR, hilang sepenuhnya secara acak. Probabilitas hilang tidak terkait dengan apa pun, baik yang teramati maupun tidak, misalnya sensor yang rusak secara acak. Jatuhping atau memasukkan data dari baris-baris ini tidak menimbulkan bias, hanya mengurangi ketelitian.
- MAR, hilang secara acak. Probabilitasnya bergantung pada variabel teramati lainnya, tetapi tidak pada nilai yang hilang itu sendiri. Jika penumpang yang lebih tua cenderung kurang tercatat usianya, maka usia tersebut bersifat MAR (Missing At Random) berdasarkan kolom-kolom lainnya. Imputasi yang menggunakan kolom-kolom tersebut dapat menangani hal ini dengan baik.
- MNAR, hilang bukan secara acak. Probabilitasnya bergantung pada nilai yang tidak teramati itu sendiri, misalnya, mereka yang berpenghasilan tinggi menolak untuk menyatakan pendapatan mereka. Tidak ada metode imputasi yang dapat memperbaiki hal ini hanya dari data saja, dan data yang hilang itu sendiri mengandung informasi yang layak dicatat dalam kolom penanda.
Imputasi rata-rata, seperti yang digunakan dalam tutorial ini, hanya dapat dibenarkan dalam kondisi MCAR dan MAR sederhana. Bahkan dalam kondisi tersebut, metode ini memiliki biaya yang diketahui: mengisi setiap celah dengan angka yang sama akan mengurangi varians kolom dan melemahkan korelasinya dengan semua hal lainnya. Untuk pekerjaan yang serius, gunakan metode berbasis model seperti paket mice, dan selalu simpan kolom penanda yang menunjukkan nilai mana yang telah diimputasi.
mengubah()
mutate() adalah dplyr Kata kerja yang membuat variabel baru atau menimpa variabel yang sudah ada, sehingga menjadikannya alat yang tepat untuk membuat salinan kolom yang sudah dibersihkan.
Kami akan melanjutkan dalam dua bagian. Kita akan belajar bagaimana:
- mengecualikan nilai yang hilang dari bingkai data
- menghubungkan nilai yang hilang dengan mean dan median
Kata kerja mutate() sangat mudah digunakan. Kita dapat membuat variabel baru dengan mengikuti sintaks berikut:
mutate(df, name_variable_1 = condition, ...) arguments: -df: Data frame used to create a new variable -name_variable_1: Name and the formula to create the new variable -...: No limit constraint. Possibility to create more than one variable inside mutate()
Kecualikan nilai yang hilang (NA)
na.omit() adalah fungsi dasar R, bukan kata kerja dplyr, tetapi tetap berfungsi dengan baik. Fungsi ini menghapus setiap baris yang berisi setidaknya satu nilai NA. Ini adalah pilihan tercepat dan jarang menjadi pilihan terbaik, karena satu nilai yang hilang akan menghapus seluruh observasi.
Untuk mengatasi masalah observasi yang hilang, kami akan menggunakan dataset Titanic. Dalam kumpulan data ini, kami memiliki akses terhadap informasi penumpang di pesawat saat tragedi tersebut. Dataset ini memiliki banyak NA yang perlu diperhatikan.
Unduh file CSV dari internet, lalu sebutkan kolom-kolom yang berisi NA:
PATH <- "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/test.csv" df_titanic <- read.csv(PATH, sep = ",") # Return the column names containing missing observations list_na <- colnames(df_titanic)[ apply(df_titanic, 2, anyNA) ] list_na
Keluaran:
## [1] "age" "fare"
Di sini,
colnames(df_titanic)[apply(df_titanic, 2, anyNA)]
Mengembalikan nama-nama kolom yang berisi setidaknya satu nilai yang hilang.
Kolom age dan fare memiliki nilai yang hilang.
Kita bisa membuangnya dengan na.omit().
library(dplyr) # Exclude the missing observations df_titanic_drop <-df_titanic %>% na.omit() dim(df_titanic_drop)
Keluaran:
## [1] 1045 13
Dataset baru berisi 1045 baris dibandingkan 1309 dengan dataset asli.
Isi data yang hilang dengan nilai rata-rata dan median.
Anda juga dapat mengisi nilai yang hilang dengan nilai rata-rata atau median. Praktik yang baik adalah membuat dua variabel terpisah untuk rata-rata dan median. Setelah dibuat, kita dapat mengganti nilai yang hilang dengan variabel yang baru dibuat.
Kami akan menggunakan metode apply untuk menghitung mean kolom dengan NA. Mari kita lihat sebuah contoh
Langkah 1) Sebelumnya di tutorial, kita menyimpan nama kolom dengan nilai yang hilang dalam daftar yang disebut list_na. Kami akan menggunakan daftar ini
Langkah 2) Hitung nilai rata-rata dengan argumen na.rm = TRUE. Argumen ini wajib karena kolom-kolom tersebut memiliki data yang hilang, dan ini memberi tahu R untuk mengabaikannya.
# Create mean average_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, mean, na.rm = TRUE) average_missing
Code Penjelasan:
Kami meneruskan 4 argumen dalam metode penerapan.
- df: df_titanic[,nama kolom(df_titanic) %dalam% list_na]. Kode ini akan mengembalikan nama kolom dari objek list_na (yaitu โusiaโ dan โtarifโ)
- 2: Hitung fungsi pada kolom
- mean: Hitung meannya
- na.rm = TRUE: Abaikan nilai yang hilang
Keluaran:
## age fare ## 29.88113 33.29548
Kami berhasil membuat mean kolom yang berisi observasi yang hilang. Kedua nilai ini akan digunakan untuk menggantikan observasi yang hilang.
Langkah 3) Ganti Nilai NA
Kata kerja mutate dari perpustakaan dplyr berguna dalam membuat variabel baru. Kita tidak serta merta ingin mengubah kolom asli sehingga kita bisa membuat variabel baru tanpa NA. mutate mudah digunakan, kita tinggal memilih nama variabel dan menentukan cara membuat variabel ini. Berikut kode lengkapnya
# Create a new variable with the mean and median df_titanic_replace <- df_titanic %>% mutate(replace_mean_age = ifelse(is.na(age), average_missing[1], age), replace_mean_fare = ifelse(is.na(fare), average_missing[2], fare))
Code Penjelasan:
Kami membuat dua variabel, replace_mean_age dan replace_mean_fare sebagai berikut:
- replace_mean_age = ifelse(is.na(usia), rata-rata_hilang[1], usia)
- replace_mean_fare = ifelse(is.na(tarif), rata-rata_hilang[2],tarif)
Jika kolom age memiliki nilai yang hilang, ganti dengan elemen pertama rata-rata_hilang (rata-rata usia), jika tidak pertahankan nilai aslinya. Logika yang sama untuk tarif
sum(is.na(df_titanic_replace$age))
Keluaran:
## [1] 263
Setelah penggantian, kolom baru tersebut tidak mengandung nilai yang hilang sama sekali:
sum(is.na(df_titanic_replace$replace_mean_age))
Keluaran:
## [1] 0
Kolom usia asli berisi 263 nilai yang hilang, sedangkan kolom replace_mean_age yang baru telah mengisi setiap nilai yang hilang tersebut dengan usia rata-rata.
Langkah 4) Kita juga bisa mengganti observasi yang hilang dengan median.
median_missing <- apply(df_titanic[,colnames(df_titanic) %in% list_na], 2, median, na.rm = TRUE) df_titanic_replace <- df_titanic %>% mutate(replace_median_age = ifelse(is.na(age), median_missing[1], age), replace_median_fare = ifelse(is.na(fare), median_missing[2], fare)) head(df_titanic_replace)
Keluaran:
Langkah 5) Pada dataset yang besar, metode langkah demi langkah menjadi membosankan. sapply() meringkas seluruh prosedur menjadi satu pernyataan, dengan konsekuensi tidak pernah melihat nilai yang diimputasi.
sapply tidak membuat a bingkai data, sehingga kita dapat menggabungkan fungsi sapply() di dalam data.frame() untuk membuat objek bingkai data.
# Quick code to replace missing values with the mean df_titanic_impute_mean <- data.frame( sapply( df_titanic, function(x) ifelse(is.na(x), mean(x, na.rm = TRUE), x)))
Imputasi Modern dengan replace_na() dan across()
Pendekatan apply() dan sapply() di atas masih berfungsi, tetapi tidyr dan dplyr sekarang mengekspresikan operasi yang sama dengan lebih aman dan lebih mudah dibaca.
replace_na() untuk nilai tetap. tidyr::replace_na() menerima daftar bernama yang berisi kolom dan penggantinya:
library(tidyr) df_titanic %>% replace_na(list(age = 29.88, fare = 33.30))
across() untuk setiap kolom numerik. Ini adalah pengganti langsung dan aman tipe untuk perintah sapply() yang dijalankan sekali baris, dan tidak seperti sapply(), perintah ini tidak pernah menyentuh kolom karakter atau faktor:
library(dplyr) # Mean-impute every numeric column df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x))) # Median-impute instead df_titanic %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), median(.x, na.rm = TRUE), .x)))
โ ๏ธ Mengapa pintasan sapply() berisiko: Contoh sapply() satu baris berjalan lebih dari setiap kolom, termasuk kolom karakter dan faktor. Memanggil mean() pada kolom tersebut akan mengembalikan NA dengan peringatan, dan sapply() kemudian akan mengubah seluruh hasilnya menjadi karakter. Versi across(where(is.numeric), โฆ) di atas sepenuhnya menghindari hal ini.
coalesce() untuk kolom cadangan. Ketika kolom kedua dapat memberikan nilai yang hilang, coalesce() mengembalikan entri pertama yang tidak hilang di antara argumennya:
df %>% mutate(age_final = coalesce(age, age_estimated, 0))
Catatlah perubahan apa saja yang Anda lakukan. Tambahkan sebuah flag sebelum memasukkan nilai, agar model selanjutnya dapat belajar dari fakta bahwa suatu nilai hilang:
df_titanic %>%
mutate(age_was_missing = is.na(age),
age = ifelse(is.na(age), mean(age, na.rm = TRUE), age))
Menangani Nilai yang Hilang di R: Referensi Metode
Tutorial ini membahas tiga pendekatan:
- Kecualikan semua pengamatan yang hilang
- Menyalahkan dengan maksudnya
- Perhitungkan dengan median
Tabel di bawah ini merangkum deteksi dan penghapusan:
| Perpustakaan | Tujuan | Code |
|---|---|---|
| mendasarkan | Buat daftar pengamatan yang hilang |
colnames(df)[apply(df, 2, anyNA)] |
| mendasarkan | Hapus setiap baris yang berisi NA |
na.omit(df) |
Imputasi dengan mean atau median dapat dilakukan dengan dua cara
- Menggunakan terapkan
- Menggunakan aplikasi
| metode | Detail | Kelebihan | Kekurangan |
|---|---|---|---|
| Langkah demi langkah dengan melamar | Periksa kolom yang hilang, hitung mean/median, simpan nilainya, ganti dengan mutate() | Anda dapat melihat nilai rata-rata atau median yang dihitung. | Waktu eksekusi lebih lama. Bisa lambat dengan kumpulan data besar |
| Cara cepat dengan sapply | Gunakan sapply() dan data.frame() untuk secara otomatis mencari dan mengganti nilai yang hilang dengan mean/median | Kode pendek dan cepat | Nilai yang dimasukkan tidak pernah ditampilkan. |



