1 persiapan Library & opsi global

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
library(knitr)
library(kableExtra)
## 
## Attaching package: 'kableExtra'
## 
## The following object is masked from 'package:dplyr':
## 
##     group_rows
library(lubridate)
library(nortest)
library(lmtest)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## 
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(car)
## 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
if (requireNamespace("DT", quietly = TRUE)) {
  library(DT)
}

2 IDENTIFIKASI DATA

Dataset yang dianalisis dalam studi ini adalah crime_incidents_messy.csv, yang bersumber dari file CSV yang diberikan untuk keperluan pemrosesan dan analisis data kejahatan. Dataset ini berisi rekam jejak insiden kriminal yang dicatat oleh pihak penegak hukum setempat.
Komponen Keterangan
Nama Dataset crime_incidents_messy.csv
Sumber Data File CSV yang diberikan
Jumlah Data 5.250 baris
Jumlah Variabel Awal 33 variabel

3 MATRIKS STRUKTUR 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)
Layout 33 Kolom Dataset Kejahatan
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

4 TUJUAN ANALISIS

  • Profil Demografi (Korban vs Tersangka): Memetakan distribusi usia, gender, dan ras pelaku serta korban pada tiap jenis kejahatan.
  • Pola Spasial & Geografis: Mengidentifikasi titik rawan (hotspot) kejahatan berdasarkan wilayah, distrik, dan koordinat.
  • Efektivitas Penegakan Hukum: Mengevaluasi tingkat penyelesaian kasus, jumlah penangkapan, dan kinerja petugas.
  • Dampak Finansial & Senjata: Menganalisis total kerugian materi serta keterkaitan penggunaan senjata dengan tingkat keparahan (severity).
  • Pola Tren Waktu: Mengetahui jam, hari, dan bulan puncak terjadinya tindakan kriminal.
  • Pembersihan Data (Data Wrangling): Menangani data hilang (missing values), typo, penyeragaman kategori, dan nilai anomali (outliers).

5 Evaluasi Kualitas Data & Isu Outlier

Secara keseluruhan, sintaks pemrograman R dibawah berfungsi untuk membuat dan menampilkan tabel ringkasan evaluasi outlier (pencilan) data agar terlihat rapi, modern, dan mudah dibaca dalam laporan atau dokumen HTML.

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)

6 STANDARISASI DATA KATEGORIK

Kategori 01
Jenis Kelamin (Gender)

Variabel suspect_gender & victim_gender diseragamkan:
• Variasi M, m, Male, MALE → Male
• Variasi F, f, Female, FEMALE → Female

Kategori 02
Ras Pelaku (Race)

Variabel suspect_race diseragamkan kapitalisasinya:
• Variasi Black, black, BLACK → Black
• Variasi White, white, WHITE → White

Kategori 03
Status Kasus (Case Status)

Variabel case_status dikoreksi dari kesalahan ketik (typo):
• Format open, OPEN → Open
• Typo Investgation → Investigation
• Typo Pendng → Pending

Kategori 04
Penyelesaian Kasus (Resolution)

Variabel resolution diseragamkan penulisan & typo-nya:
• Format NO ARREST → No Arrest
• Typo Arres Made → Arrest Made

Kategori 05
Pelaporan Online

Variabel reported_online dikonversi ke format standar:
• Nilai TRUE, Yes, 1 → Yes
• Nilai FALSE, No, 0 → No

Kategori 06
Tingkat Keparahan (Severity)

Variabel severity dipetakan kodenya:
• Kode angka 1 hingga 4 dipetakan ke skala kategorikal Low hingga Critical setelah validasi data.

7 NILAI NUMERIK YANG TIDAK VALID

Variabel 01
Usia Tersangka (Suspect Age)

Variabel suspect_age memiliki nilai anomali ekstrem:
• Nilai -28, 162, 262 → Tidak masuk akal secara biologis, ditandai sebagai Invalid / Missing (NA).

Variabel 02
Usia Korban (Victim Age)

Variabel victim_age memiliki nilai bernilai negatif/ekstrem:
• Nilai -41, -65, 231, 292 → Dategori tidak valid, diubah menjadi NA.

Variabel 03
Jumlah Penangkapan (Num Arrests)

Variabel num_arrests bernilai negatif:
• Nilai -5 dan -1 → Tidak valid karena jumlah penangkapan bersifat pencacahan (non-negatif).

Variabel 04
Kerugian Kerusakan (Property Loss USD)

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.

8 VALIDASILOKASI & FORMAT TUNGGAL

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

9 KESIMPULAN

Evaluasi Kualitas Data

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].

Cakupan Pembersihan

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].

Hasil Akhir & Kesiapan Data

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].

10 METADATA: DATA TENTANG DATA

Dokumentasi Data
Apa Itu Metadata?
WHO?
Data ini dikumpulkan oleh pihak kepolisian setempat atau lembaga penegak hukum di tingkat kabupaten/kota[cite: 7].
WHAT?
Dataset ini berisi catatan atau jejak insiden tindak kriminal dan kejahatan yang terjadi di daerah setempat[cite: 7].
WHY?
Dokumentasi & Administrasi Hukum: Merekam secara resmi setiap laporan kejahatan untuk penyelidikan, penuntutan, serta pembuatan catatan medis dan hukum perkara[cite: 7].
WHEN?
Rentang waktu perekaman data dari 24 Januari 2018 (15:33) sampai dengan 14 November 2024 (06:49)[cite: 7].
WHERE? (Cakupan Wilayah Negara Bagian di Amerika Serikat)[cite: 7]
GA Georgia
OH Ohio
AZ Arizona
PA Pennsylvania
CA California
TX Texas
IL Illinois
NY New York
FL Florida
NC North Carolina
  • 40 Negara Bagian Lainnya (Total 50 AS)

11 APA ITU METADATA?

Unit Observasi
Struktur Baris Data

Unit observasi dalam dataset ini adalah satu kejadian kejahatan (crime incident), di mana 1 baris data mewakili 1 kasus yang dicatat[cite: 7]. Setiap kejadian memiliki variabel spesifik seperti jenis kejahatan, lokasi, tanggal, demografi korban/tersangka, umur, senjata, tingkat keparahan, hingga status kasus[cite: 7].

Format Data
Dimensi & Pengolahan
Data disajikan dalam bentuk tabel/dataset terstruktur[cite: 7]:

📊 5.250 Baris 📋 33 Kolom

Format data fleksibel untuk digunakan dalam bentuk file CSV maupun Excel, sehingga siap diolah menggunakan aplikasi spreadsheet atau environment RStudio/Python[cite: 7].

Metode (HOW)
Pengumpulan Data

Data dikumpulkan melalui pencatatan sistematis setiap laporan dan insiden kejahatan yang terjadi[cite: 7]. Seluruh informasi dihimpun dari laporan resmi penegak hukum dan disusun ke dalam tabel terstruktur mencakup identitas perkara, lokasi, keterlibatan pihak, hingga instrumen senjata yang digunakan[cite: 7].

12 DATA DICTIONARY

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 -

13 ALUR PREPROCESSING DATA CLEANING

memasukan data terlebih dahulu ke R studio, tapi disini saya hanya menampilkan 10 data teratas saja karena kalau saya tampilkan semua itu akan memakan 5000 lebih data, jadi agar lebih rapi saya ambil 10 data teratas

df <- read.csv("data ade 22.csv", sep = ";")
head(df, 10)
##             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
PROSES CLEANING DAN IMPUTASI MEDIAN

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)
  )
hitung meidan usia korban & tersangka

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
med_v
## [1] 50
setelah kita dapat nilai median nya maka selanjutnya kita melakukan imputasi yaitu merubah NA menjadi angka median yang kita dapatkan, dan saya akan tetap menampilkan 50 data teratas agar tidak terlalu banyak data yang ada di R pubs

# 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)
  )
PROSES CLEANING DAN IMPUTASI MEDIAN

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).

library(dplyr)
df_clean <- df %>%
  mutate(
    v_num = as.numeric(sub("\\..*", "", victim_age)),
    s_num = as.numeric(sub("\\..*", "", suspect_age)),
    
    v_clean = ifelse(v_num >= 0 & v_num <= 100, v_num, NA),
    s_clean = ifelse(s_num >= 0 & s_num <= 100, s_num, NA)
  )

14 UJI NORMALITAS, UJI HETEROPSKEDASTISITAS, UJI AUTOKORELASI DAN UJI LEVENE`S

DISTRIBUSI DATA

Uji Normalitas

Berguna untuk mengetahui apakah data sampel berasal dari populasi yang berdistribusi normal atau apakah residual terdistribusi secara normal.

VARIANS RESIDUAL

Uji Heteroskedastisitas

Berguna untuk menguji apakah terdapat ketidaksamaan varians dari residual satu pengamatan ke pengamatan yang lain dalam model regresi.

KORELASI SERI

Uji Autokorelasi

Berguna menguji apakah ada korelasi antara kesalahan pengganggu (residual) pada periode t dengan kesalahan pengganggu pada periode sebelumnya (t-1) dalam model regresi.

HOMOGENITAS

Uji Levene’s

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
qqnorm(residuals(model), main = "Q-Q Plot Residual")
qqline(residuals(model), col = "red", lwd = 2)
Uji Normalitas Residual (Lilliefors Test)Pengujian normalitas dilakukan untuk melihat apakah nilai error/residual dari model regresi berdistribusi normal. Berdasarkan hasil pengujian Lilliefors (Kolmogorov-Smirnov) pada residual model, diperoleh nilai statistik tes \(D = 0.14809\) dengan \(p\text{-value} < 2.2 \times 10^{-16}\). Karena \(p\text{-value} < 0.05\), maka keputusan yang diambil adalah menolak \(H_0\), yang menunjukkan bahwa residual model tidak berdistribusi normal. Catatan Tambahan untuk Pembahasan:Ketidaknormalan residual ini sering kali disebabkan oleh ditemukannya nilai pencilan (outliers), distribusi data usia yang miring (skewed), atau ukuran sampel yang cukup besar sehingga uji formal menjadi sangat sensitif terhadap deviasi kecil dari distribusi normal.

bptest(model)
## 
##  studentized Breusch-Pagan test
## 
## data:  model
## BP = 0.72186, df = 1, p-value = 0.3955
Pengujian Breusch-Pagan dilakukan untuk memastikan bahwa varians dari error/residual bersifat konstan (homoskedastisitas). Berdasarkan output pengujian, diperoleh statistik uji \(BP = 0.72186\) dengan \(p\text{-value} = 0.3955\). Karena nilai \(p\text{-value} > 0.05\), kita gagal menolak \(H_0\), yang berarti asumsi homoskedastisitas terpenuhi dan tidak terjadi masalah heteroskedastisitas pada model.

dwtest(model)
## 
##  Durbin-Watson test
## 
## data:  model
## DW = 1.9461, p-value = 0.02547
## alternative hypothesis: true autocorrelation is greater than 0
Uji Durbin-Watson digunakan untuk mendeteksi keberadaan korelasi antara residual pada periode/pengamatan tertentu. Hasil pengujian menunjukkan nilai statistik \(DW = 1.9461\) dengan \(p\text{-value} = 0.02547\). Karena \(p\text{-value} < 0.05\), hipotesis nol ditolak, yang menunjukkan terdapat indikasi autokorelasi positif pada residual model secara statistik.

leveneTest(victim_age_clean ~ crime_type, data = df_clean)
## 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
Pengujian homogenitas varians dilakukan menggunakan Levene’s Test (berdasarkan nilai median) untuk mengecek apakah varians variabel respon antar kategori/kelompok bersifat sama.Berdasarkan output pengujian, diperoleh nilai statistik \(F = 1.3013\) dengan \(p\text{-value} = 0.004683\). Karena nilai \(p\text{-value} < 0.05\), maka keputusan yang diambil adalah menolak \(H_0\). Hal ini menunjukkan bahwa asumsi homogenitas varians tidak terpenuhi (varians antar kelompok tidak sama secara signifikan).

15 ENCODING

panggil packages
PENJELASAN TAHAP ENCODING:

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
  )
)