Secara keseluruhan, syntax dibawah digunakan untuk mempersiapkan lingkungan kerja R sebelum melakukan proses analisis data. Pengaturan knitr digunakan agar kode, pesan, peringatan, dan hasil visualisasi dapat ditampilkan dengan lebih teratur dalam laporan, sedangkan pemanggilan Tidyverse menyediakan berbagai fungsi yang diperlukan untuk membaca, membersihkan, mengolah, menganalisis, dan memvisualisasikan data. Dengan demikian, tahap ini memastikan lingkungan analisis sudah siap digunakan dan hasil analisis dapat disajikan secara lebih rapi dan konsisten.
# Pengaturan Global Chunk
knitr::opts_chunk$set(
echo = TRUE,
warning = FALSE,
message = FALSE,
fig.width = 9,
fig.height = 5.5,
fig.align = "center"
)
# Memanggil Seluruh Library
library(tidyverse)## ── 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 errors
##
## Attaching package: 'kableExtra'
##
## The following object is masked from 'package:dplyr':
##
## group_rows
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
## Loading required package: carData
##
## Attaching package: 'car'
##
## The following object is masked from 'package:dplyr':
##
## recode
##
## The following object is masked from 'package:purrr':
##
## some
| Komponen | Keterangan |
|---|---|
| Nama Dataset | crime_incidents_messy.csv |
| Sumber Data | File CSV yang diberikan |
| Jumlah Data | 5.250 baris |
| Jumlah Variabel Awal | 33 variabel |
menampilkan tabel nama-nama variabel dari data yang kami olah
# Menyusun tata letak variabel 5 baris x 8 kolom
matriks_tabel <- matrix(
c(
"incident_id", "crime_type", "district", "city", "state", "address", "latitude", "longitude",
"incident_datetime", "officer_id", "officer_first_name", "officer_last_name", "badge_number", "suspect_id", "suspect_first_name", "suspect_last_name",
"suspect_age", "suspect_gender", "suspect_race", "victim_id", "victim_first_name", "victim_last_name", "victim_age", "victim_gender",
"victim_phone", "weapon_used", "severity", "case_status", "resolution", "num_arrests", "property_loss_usd", "reported_online",
"notes", "-", "-", "-", "-", "-", "-", "-"
),
nrow = 5,
ncol = 8,
byrow = TRUE
)
# Menampilkan Tabel Matriks
kable(matriks_tabel, col.names = paste("Kolom", 1:8), caption = "Layout 33 Kolom Dataset Kejahatan") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = TRUE) %>%
row_spec(0, background = "#1e3c72", color = "white", bold = TRUE)| Kolom 1 | Kolom 2 | Kolom 3 | Kolom 4 | Kolom 5 | Kolom 6 | Kolom 7 | Kolom 8 |
|---|---|---|---|---|---|---|---|
| incident_id | crime_type | district | city | state | address | latitude | longitude |
| incident_datetime | officer_id | officer_first_name | officer_last_name | badge_number | suspect_id | suspect_first_name | suspect_last_name |
| suspect_age | suspect_gender | suspect_race | victim_id | victim_first_name | victim_last_name | victim_age | victim_gender |
| victim_phone | weapon_used | severity | case_status | resolution | num_arrests | property_loss_usd | reported_online |
| notes |
|
|
|
|
|
|
|
library(knitr)
library(kableExtra)
# Membuat Data Frame Outlier
tabel_outlier <- data.frame(
Variabel = c("latitude", "longitude", "suspect_age", "victim_age", "num_arrests"),
Jumlah_Outlier = c(184, 206, 314, 318, 74),
Keterangan = c(
"Di luar rentang -90 s/d 90 (tertukar / salah input)",
"Koordinat di luar batas wilayah rasional",
"Nilai ekstrem/tidak masuk akal (misal: -28, 162, 262)",
"Nilai bernilai negatif/ekstrem (misal: -41, -65, 231)",
"Jumlah penangkapan bernilai negatif (-5, -1)"
)
)
# Menampilkan Tabel Outlier Bergaya Modern
kable(tabel_outlier, col.names = c("Nama Variabel", "Jumlah Outlier", "Keterangan Ringkas")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = TRUE) %>%
row_spec(0, background = "#0f172a", color = "white", bold = TRUE) %>%
column_spec(2, bold = TRUE, color = "#dc3545")| Nama Variabel | Jumlah Outlier | Keterangan Ringkas |
|---|---|---|
| latitude | 184 | Di luar rentang -90 s/d 90 (tertukar / salah input) |
| longitude | 206 | Koordinat di luar batas wilayah rasional |
| suspect_age | 314 | Nilai ekstrem/tidak masuk akal (misal: -28, 162, 262) |
| victim_age | 318 | Nilai bernilai negatif/ekstrem (misal: -41, -65, 231) |
| num_arrests | 74 | Jumlah penangkapan bernilai negatif (-5, -1) |
Variabel suspect_gender & victim_gender
diseragamkan:
• Variasi M, m,
Male, MALE → Male
• Variasi F,
f, Female, FEMALE → Female
Variabel suspect_race diseragamkan kapitalisasinya:
• Variasi Black, black, BLACK →
Black
• Variasi
White, white, WHITE → White
Variabel case_status dikoreksi dari kesalahan ketik
(typo):
• Format open, OPEN → Open
• Typo Investgation
→ Investigation
• Typo
Pendng → Pending
Variabel resolution diseragamkan penulisan &
typo-nya:
• Format NO ARREST → No Arrest
• Typo Arres
Made → Arrest Made
Variabel reported_online dikonversi ke format
standar:
• Nilai TRUE, Yes, 1
→ Yes
• Nilai
FALSE, No, 0 → No
Variabel severity dipetakan kodenya:
• Kode angka
1 hingga 4 dipetakan ke skala kategorikal
Low hingga Critical setelah validasi data.
Variabel suspect_age memiliki nilai anomali ekstrem:
• Nilai -28, 162, 262 → Tidak
masuk akal secara biologis, ditandai sebagai Invalid / Missing
(NA).
Variabel victim_age memiliki nilai bernilai
negatif/ekstrem:
• Nilai -41, -65,
231, 292 → Dategori tidak valid, diubah
menjadi NA.
Variabel num_arrests bernilai negatif:
• Nilai
-5 dan -1 → Tidak valid karena jumlah
penangkapan bersifat pencacahan (non-negatif).
Variabel property_loss_usd bernilai minus:
• Nilai
-34291.84 → Diperiksa khusus karena nilai kerugian moneter
tercatat sebagai nilai positif.
Catatan Penting Penanganan Data: Nilai tidak valid (invalid/anomali) tidak diperbolehkan diganti secara konseptual (imputasi sembarangan) tanpa memastikan nilai sebenarnya dari sumber dokumentasi data mentah.
latitude harus berada pada rentang -90 sampai 90 contoh 108.6542 dan 170.2841 tidak valid sebagai latitude dan perlu diperiksa, kemungkinan penyebab tertukar dengan longitude atau kesalahan input, format tanggal juga haruas di seragamkan agar mudah dibaca komputer, contoh: 4/16/2024 8:45 menjadi 2024-04-16 08:45
Dataset awal menunjukkan beberapa isu kualitas yang signifikan, meliputi
keberadaan missing values, ketidakseragaman variabel
kategorik, kesalahan pengetikan (typo), hingga anomali pada
nilai numerik dan koordinat spasial[cite: 8]. Penanganan nilai tidak
valid dilakukan secara teliti berdasarkan konfirmasi sumber data asli
sebelum dikonversi menjadi NaN atau Unknown
tanpa imputasi sembarangan[cite: 8].
Proses pembersihan data (data cleaning) mencakup perbaikan dan standarisasi menyeluruh[cite: 8]. Tindakan ini meliputi koreksi nama kategori, penyelarasan format tanggal dan nilai biner, pemeriksaan batas logis numerik, hingga penyelarasan koordinat geografis[cite: 8]. Langkah-langkah ini memastikan seluruh variabel memiliki struktur data yang bersih dan konsisten[cite: 8].
Melalui seluruh tahapan validasi dan standarisasi tersebut, dataset kini telah memenuhi standar kualitas data yang baik[cite: 8]. Data berada dalam kondisi yang konsisten, valid, dan siap digunakan untuk analisis eksploratif maupun pemodelan statistik selanjutnya[cite: 8].
Data dictionary adalah dokumen yang menjelaskan struktur, arti, dan isi dari setiap variabel dalam sebuah dataset. Sederhananya, data dictionary berfungsi seperti “kamus” yang membantu kita memahami data.Jadi, data dictionary digunakan sebagai acuan saat melakukan data cleaning dan standardisasi, terutama untuk memastikan bahwa kita tidak salah mengartikan kode atau nilai yang ada di dalam dataset.
| No | Nama Variabel | Deskripsi | Tipe | Satuan |
|---|---|---|---|---|
| 1 | incident_id | ID unik untuk setiap kejadian kriminal | Kategorik/ID | - |
| 2 | crime_type | Jenis atau kategori tindak kriminal | Kategorik | - |
| 3 | district | Wilayah atau distrik tempat kejadian | Kategorik | - |
| 4 | city | Wilayah atau distrik tempat kejadian | Kategorik | - |
| 5 | state | Negara bagian lokasi kejadian | Kategorik | kode wilayah |
| 6 | address | Alamat lokasi kejadian | Kategorik | - |
| 7 | latitude | Koordinat lintang lokasi kejadian | Numerik | Derajat |
| 8 | longitude | Koordinat bujur lokasi kejadian | Numerik | Derajat |
| 9 | incident_datetime | Tanggal dan waktu kejadian kriminal | Tanggal/Waktu | Tanggal & waktu |
| 10 | officer_id | ID unik petugas yang menangani kejadian | Kategorik/ID | - |
| 11 | officer_first_name | Nama depan petugas | Kategorik/Teks | - |
| 12 | officer_last_name | Nama belakang petugas | Kategorik/Teks | - |
| 13 | badge_number | Nomor lencana petugas | Numerik/ID | - |
| 14 | suspect_id | ID unik tersangka | Kategorik/ID | - |
| 15 | suspect_first_name | Nama depan tersangka | Kategorik/Teks | - |
| 16 | suspect_last_name | Nama belakang tersangka | Kategorik/Teks | - |
| 17 | suspect_age | Usia tersangka saat kejadian | Numerik | Tahun |
| 18 | suspect_gender | Jenis kelamin tersangka | Kategorik | - |
| 19 | suspect_race | Ras/kelompok etnis tersangka pada data awal | Kategorik/ID | - |
| 20 | victim_id | ID unik korban | Kategorik/ID | - |
| 21 | victim_first_name | Nama depan korban | Kategorik/Teks | - |
| 22 | victim_last_name | Nama belakang korban | Kategorik/Teks | - |
| 23 | victim_age | Usia korban pada data awal | Numerik | Tahun |
| 24 | victim_gender | Jenis kelamin korban pada data awal | Kategorik | - |
| 25 | victim_phone | Nomor telepon korban | Kategorik/Teks | Nomor Telepon |
| 26 | weapon_used | Jenis senjata yang digunakan dalam kejadian | Kategorik | - |
| 27 | severity | Tingkat keparahan kejadian | Kategorik/Ordinal | Skor |
| 28 | case_status | Status penanganan kasus | Kategorik | - |
| 29 | resolution | Hasil atau penyelesaian kasus | Kategorik | - |
| 30 | num_arrests | Jumlah penangkapan yang terkait dengan kasus | Numerik | Orang |
| 31 | property_loss_usd | Nilai kerugian properti akibat kejadian | Numerik | USD |
| 32 | reported_online | Indikator apakah kejadian dilaporkan secara online | Kategorik/Biner | Ya/Tidak |
| 33 | notes | Catatan atau keterangan tambahan mengenai kejadian | Teks | - |
## crime_type victim_id Victim.Name victim_age victim_gender
## 1 asslt VIC00642 Robert Torres 51 Unknown
## 2 burglary VIC00262 John Martin 231
## 3 Homocide VIC00518 Richard Hill 29 Other
## 4 Property Damage VIC00243 Susan Young 243 N/A
## 5 Domestc Violence VIC00512 Thomas Thomas 51 M
## 6 Breaking & Entering VIC00473 Anthony Wilson 15 N/A
## 7 robbery VIC00429 Mary Walker 72 female
## 8 manslaughter VIC00904 David Torres female
## 9 B&E VIC00093 Mary Lee 55 Other
## 10 Homocide VIC00859 Michelle Hill 10 N/A
## suspect_id Suspect.Name suspect_age suspect_gender suspect_race
## 1 SUS00281 Barbara Thomas 51.00.00 MALE asian
## 2 SUS00376 Barbara Harris -28 Other Black
## 3 SUS00560 Richard Scott 19 F asian
## 4 SUS00468 Michael Thomas 262 MALE Black
## 5 SUS00751 Thomas Jackson 75 female white
## 6 SUS00454 James Lee 73 N/A White
## 7 SUS00623 Carol Harris 58 Female Unknown
## 8 SUS00533 Jennifer Taylor 73 MALE White
## 9 SUS00320 Robert Hill 26 m Hispanic
## 10
Secara keseluruhan, syntax tersebut digunakan untuk melakukan data cleaning pada variabel usia. Prosesnya dimulai dengan mengambil dan mengubah data usia menjadi angka, kemudian melakukan pemeriksaan terhadap rentang usia. Nilai usia yang dianggap tidak masuk akal tidak langsung diganti dengan angka tertentu, tetapi diubah menjadi NA agar dapat ditangani sebagai missing value pada tahap analisis selanjutnya.
Jadi, tujuan utamanya adalah memastikan data usia yang digunakan dalam analisis berada pada rentang yang telah ditentukan dan mengurangi pengaruh nilai usia yang tidak valid.df_clean <- df %>%
mutate(
victim_age_num = as.numeric(sub("\\..*", "", victim_age)),
suspect_age_num = as.numeric(sub("\\..*", "", suspect_age)),
# MEMBUAT KOLOM victim_age_clean DULU DI SINI:
victim_age_clean = ifelse(victim_age_num >= 0 & victim_age_num <= 100, victim_age_num, NA),
suspect_age_clean = ifelse(suspect_age_num >= 0 & suspect_age_num <= 100, suspect_age_num, NA)
)Syntax R tersebut digunakan untuk menghitung nilai tengah (median) usia dari dua kelompok data yang telah dibersihkan pada data frame df_clean_final, yaitu data usia korban dan usia tersangka.Proses perhitungan dilakukan menggunakan fungsi median(), yang diterapkan pada kolom victim_age_clean untuk kelompok korban dan kolom suspect_age_clean untuk kelompok tersangka. Dalam kedua perhitungan tersebut, disertakan argumen na.rm = TRUE agar nilai yang kosong atau hilang (missing value/NA) diabaikan secara otomatis sehingga tidak merusak hasil perhitungan statistik. dan didapatlah angka 46 untuk korban dan 50 untuk tersangka
med_v <- median(df_clean$victim_age_clean, na.rm = TRUE)
med_s <- median(df_clean$suspect_age_clean, na.rm = TRUE)
med_s## [1] 46
## [1] 50
# Hitung median dari data yang valid
med_v <- median(df_clean$victim_age_clean, na.rm = TRUE)
med_s <- median(df_clean$suspect_age_clean, na.rm = TRUE)
# Lakukan imputasi NA dengan nilai median
df_clean <- df_clean %>%
mutate(
victim_age_clean = ifelse(is.na(victim_age_clean), med_v, victim_age_clean),
suspect_age_clean = ifelse(is.na(suspect_age_clean), med_s, suspect_age_clean),
crime_type = as.factor(crime_type)
)Secara keseluruhan, kode R tersebut berfungsi untuk membersihkan data umur korban (victim_age) dan pelaku (suspect_age) dengan cara membuang karakter yang tidak perlu, mengubah format menjadi angka, serta menyaring nilai-nilai anomali (outlier) agar berada dalam rentang wajar (0 hingga 100 tahun).
Berguna untuk mengetahui apakah data sampel berasal dari populasi yang berdistribusi normal atau apakah residual terdistribusi secara normal.
Berguna untuk menguji apakah terdapat ketidaksamaan varians dari residual satu pengamatan ke pengamatan yang lain dalam model regresi.
Berguna menguji apakah ada korelasi antara kesalahan pengganggu (residual) pada periode t dengan kesalahan pengganggu pada periode sebelumnya (t-1) dalam model regresi.
Berguna untuk menguji kesamaan varians (homogenitas varians) antara dua kelompok data atau lebih.
library(dplyr)
library(nortest)
library(lmtest)
library(car)
# 1. Baca Data
df <- read.csv("data ade 22.csv", sep = ";")
# 2. Buat kolom victim_age_clean & suspect_age_clean PERTAMA KALI
df_clean <- df %>%
mutate(
victim_age_num = as.numeric(sub("\\..*", "", victim_age)),
suspect_age_num = as.numeric(sub("\\..*", "", suspect_age)),
# Memfilter rentang usia valid (0 - 100 tahun)
victim_age_clean = ifelse(victim_age_num >= 0 & victim_age_num <= 100, victim_age_num, NA),
suspect_age_clean = ifelse(suspect_age_num >= 0 & suspect_age_num <= 100, suspect_age_num, NA)
)
# 3. Hitung Median
med_v <- median(df_clean$victim_age_clean, na.rm = TRUE)
med_s <- median(df_clean$suspect_age_clean, na.rm = TRUE)
# 4. Lakukan Imputasi Nilai NA dengan Median (Baru panggil is.na setelah kolom dibuat!)
df_clean <- df_clean %>%
mutate(
victim_age_clean = ifelse(is.na(victim_age_clean), med_v, victim_age_clean),
suspect_age_clean = ifelse(is.na(suspect_age_clean), med_s, suspect_age_clean),
crime_type = as.factor(crime_type)
)
# 5. Model Regresi & Uji Asumsi
model <- lm(suspect_age_clean ~ victim_age_clean, data = df_clean)
lillie.test(residuals(model))##
## Lilliefors (Kolmogorov-Smirnov) normality test
##
## data: residuals(model)
## D = 0.14809, p-value < 2.2e-16
##
## studentized Breusch-Pagan test
##
## data: model
## BP = 0.72186, df = 1, p-value = 0.3955
##
## Durbin-Watson test
##
## data: model
## DW = 1.9461, p-value = 0.02547
## alternative hypothesis: true autocorrelation is greater than 0
## Levene's Test for Homogeneity of Variance (center = median)
## Df F value Pr(>F)
## group 181 1.3013 0.004683 **
## 5067
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Tahap encoding dan rekayasa fitur (feature engineering) bertujuan untuk mengubah variabel kategorikal dan teks/ID menjadi format yang terstruktur serta siap digunakan untuk pemodelan statistik atau algoritma Machine Learning.
Sintaks ini bertujuan untuk melakukan one-hot encoding (membuat kolom variabel dummy berangka 0 dan 1) pada kolom victim_gender dan victim_age_group guna mengubah data kategorikal menjadi format numerik yang siap digunakan untuk pemodelan data.
library(dplyr)
library(readr)
# Gunakan read_csv2 untuk file yang menggunakan pemisah titik koma (;)
data_crime <- read_csv2("data ade 22.csv")
data_crime <- data_crime %>%
mutate(
victim_age_group = case_when(
victim_age < 18 ~ "Anak-Anak",
victim_age >= 18 & victim_age <= 35 ~ "Dewasa Muda",
victim_age >= 36 & victim_age <= 60 ~ "Dewasa",
victim_age > 60 ~ "Lansia",
TRUE ~ "Tidak Diketahui"
)
)one hot
library(fastDummies)
library(dplyr)
# 1. Pilih nama dataframe yang aktif di memori
df_target <- if (exists("data_crime")) data_crime else df_clean
# 2. Cari kolom yang benar-benar ada di dataframe
cols_to_encode <- intersect(
c("victim_gender_clean", "victim_gender", "victim_age_group", "crime_type_clean", "crime_type"),
names(df_target)
)
# 3. Jalankan dummy_cols pada kolom yang ditemukan saja
if (length(cols_to_encode) > 0) {
data_crime_encoded <- dummy_cols(
df_target,
select_columns = cols_to_encode,
remove_first_dummy = TRUE,
remove_selected_columns = FALSE
)
} else {
message("Kolom untuk encoding belum ditemukan. Nama kolom yang ada saat ini:")
print(names(df_target))
}lalu membersihkan data dan menyeragamkan semuaa nyaaa
library(dplyr)
library(stringr)
library(DT)
# 1. FUNSI BANTUAN UNTUK MENCARI MODUS (KATEGORI TERBANYAK)
get_mode <- function(v) {
v_clean <- v[!is.na(v) & !(v %in% c("Unknown", "Other", "N/A", ""))]
if (length(v_clean) == 0) return("Unspecified")
names(which.max(table(v_clean)))
}
# 2. PROSES PEMBERSIHAN DAN IMPUTASI UNTUK SELURUH KOLOM
df_clean_full <- df %>%
# A. Cleaning & Standardisasi Kejahatan (Termasuk B&E)
mutate(
crime_type = case_when(
grepl("asslt|assault", crime_type, ignore.case = TRUE) ~ "Assault & Battery",
grepl("burglary|b&e|breaking", crime_type, ignore.case = TRUE) ~ "Burglary/B&E",
grepl("homocide|homicide", crime_type, ignore.case = TRUE) ~ "Homicide",
grepl("property", crime_type, ignore.case = TRUE) ~ "Property Damage",
grepl("domestc|domestic", crime_type, ignore.case = TRUE) ~ "Domestic Violence",
grepl("robbery", crime_type, ignore.case = TRUE) ~ "Robbery",
grepl("manslaughter", crime_type, ignore.case = TRUE) ~ "Manslaughter",
TRUE ~ str_to_title(crime_type)
)
) %>%
# B. Imputasi Outlier & Usia Korban
mutate(
victim_age = suppressWarnings(as.numeric(victim_age)),
victim_age = ifelse(victim_age > 100 | victim_age < 0 | is.na(victim_age), NA, victim_age)
) %>%
mutate(
victim_age = ifelse(is.na(victim_age), round(median(victim_age, na.rm = TRUE)), victim_age)
) %>%
# C. Standardisasi & Imputasi Gender Korban (Mengganti Unknown/Other/NA dengan Modus)
mutate(
victim_gender = case_when(
victim_gender %in% c("M", "Male", "male") ~ "Male",
victim_gender %in% c("F", "Female", "female") ~ "Female",
TRUE ~ NA_character_
)
)
# Imputasi Gender dengan Modus (Nilai yang paling sering muncul)
mode_gender <- get_mode(df_clean_full$victim_gender)
df_clean_full <- df_clean_full %>%
mutate(
victim_gender = ifelse(is.na(victim_gender), mode_gender, victim_gender)
)
# 3. OVERWRITE DATAFRAME UTAMA
df <- df_clean_full
# 4. TAMPILKAN TABEL UTAMA UNTUK SELURUH BARIS DATA (SELESAI KESELURUHAN)
datatable(
df,
caption = "Tabel Data Keseluruhan yang Sudah Bersih dan Terimputasi Lengkap",
options = list(
scrollX = TRUE,
pageLength = 10,
lengthMenu = c(10, 25, 50, 100, 500, 1000),
autoWidth = TRUE
)
)# 1. FUNSI MENCARI MODUS GENDER (TERBANYAK ANTARA MALE / FEMALE)
get_gender_mode <- function(v) {
v_clean <- v[!is.na(v) & v %in% c("Male", "Female")]
if (length(v_clean) == 0) return("Male")
names(which.max(table(v_clean)))
}
# 2. STANDARISASI GENDER KORBAN & TERSANGKA
df <- df %>%
mutate(
# Format Victim Gender
victim_gender = case_when(
tolower(victim_gender) %in% c("m", "male") ~ "Male",
tolower(victim_gender) %in% c("f", "female") ~ "Female",
TRUE ~ NA_character_ # N/A, Unknown, Other, Kosong diubah ke NA
),
# Format Suspect Gender
suspect_gender = case_when(
tolower(suspect_gender) %in% c("m", "male") ~ "Male",
tolower(suspect_gender) %in% c("f", "female") ~ "Female",
TRUE ~ NA_character_ # N/A, Unknown, Other, Kosong diubah ke NA
)
)
# 3. IMPUTASI NILAI NA/KOSONG DENGAN MODUS
victim_mode <- get_gender_mode(df$victim_gender)
suspect_mode <- get_gender_mode(df$suspect_gender)
df <- df %>%
mutate(
victim_gender = ifelse(is.na(victim_gender), victim_mode, victim_gender),
suspect_gender = ifelse(is.na(suspect_gender), suspect_mode, suspect_gender)
)
# 4. TAMPILKAN TABEL HASIL PENSERAGAMAN
datatable(
df,
caption = "Tabel Data Setelah Penyeragaman Gender (Male & Female Saja)",
options = list(
scrollX = TRUE,
pageLength = 10,
lengthMenu = c(10, 25, 50, 100),
autoWidth = TRUE
)
)