Laporan ini mengeksplorasi data insiden kriminal yang telah melalui proses pembersihan. Fokus analisis diarahkan pada karakteristik korban dan tersangka, distribusi kategori kejahatan, serta hubungan sederhana antara usia korban dan usia tersangka. Dataset akhir yang digunakan berisi 5.249 observasi dan 10 variabel.
Analisis bersifat deskriptif dan eksploratif, sehingga hasilnya digunakan untuk menggambarkan pola dalam data, bukan untuk menyimpulkan hubungan sebab-akibat.
Data kriminal dapat digunakan untuk melihat gambaran umum mengenai karakteristik korban, tersangka, dan jenis kejahatan yang tercatat. Sebelum dilakukan analisis, data perlu diperiksa agar format variabel lebih konsisten dan nilai yang tidak wajar dapat ditangani.
Pada proyek ini digunakan data hasil cleaning kelompok yang memuat informasi identitas korban dan tersangka, usia, jenis kelamin, ras tersangka, serta kategori kejahatan. Proses eksplorasi dilakukan dengan bantuan R agar pemeriksaan dan visualisasi dapat direproduksi.
Tujuan analisis adalah:
Data berasal dari file Crime_Incidents_Clean Kelompok Mantull.xlsx, yaitu data kriminal yang telah melalui tahap cleaning. Unit observasinya adalah satu catatan insiden/kejadian kriminal.
library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
data <- read_excel("Crime_Incidents_Clean Kelompok Mantull.xlsx")
names(data) <- make.names(names(data))
cat("Jumlah baris:", nrow(data), "\n")
## Jumlah baris: 5249
cat("Jumlah variabel:", ncol(data), "\n")
## Jumlah variabel: 10
variabel <- data.frame(
Variabel = names(data),
Keterangan = c(
"ID korban",
"Nama korban",
"Usia korban setelah cleaning",
"Jenis kelamin korban setelah cleaning",
"ID tersangka",
"Nama tersangka",
"Usia tersangka setelah cleaning",
"Jenis kelamin tersangka setelah cleaning",
"Ras tersangka setelah cleaning",
"Kategori kejahatan"
)
)
knitr::kable(variabel, caption = "Daftar variabel pada dataset akhir")
| Variabel | Keterangan |
|---|---|
| Victim.ID | ID korban |
| Victim.Name | Nama korban |
| Victim.Age.Clean | Usia korban setelah cleaning |
| Victim.Gender.Clean | Jenis kelamin korban setelah cleaning |
| Suspect.ID | ID tersangka |
| Suspect.Name | Nama tersangka |
| Suspect.Age.Clean | Usia tersangka setelah cleaning |
| Suspect.Gender.Clean | Jenis kelamin tersangka setelah cleaning |
| Suspect.Race.Clean | Ras tersangka setelah cleaning |
| Crime.Category | Kategori kejahatan |
str(data)
## tibble [5,249 × 10] (S3: tbl_df/tbl/data.frame)
## $ Victim.ID : chr [1:5249] "VIC00642" "VIC00262" "VIC00518" "VIC00243" ...
## $ Victim.Name : chr [1:5249] "Robert Torres" "John Martin" "Richard Hill" "Susan Young" ...
## $ Victim.Age.Clean : num [1:5249] 51 50 29 50 51 15 72 50 55 10 ...
## $ Victim.Gender.Clean : chr [1:5249] "Unknown" "Unknown" "Other" "Unknown" ...
## $ Suspect.ID : chr [1:5249] "SUS00281" "SUS00376" "SUS00560" "SUS00468" ...
## $ Suspect.Name : chr [1:5249] "Barbara Thomas" "Barbara Harris" "Richard Scott" "Michael Thomas" ...
## $ Suspect.Age.Clean : num [1:5249] 51 46 19 46 75 73 58 73 26 46 ...
## $ Suspect.Gender.Clean: chr [1:5249] "Male" "Other" "Female" "Male" ...
## $ Suspect.Race.Clean : chr [1:5249] "Asian" "Black" "Asian" "Black" ...
## $ Crime.Category : chr [1:5249] "Assault & Battery" "Burglary / B&E" "Other" "Property Damage" ...
knitr::kable(head(data, 8), caption = "Delapan observasi pertama")
| Victim.ID | Victim.Name | Victim.Age.Clean | Victim.Gender.Clean | Suspect.ID | Suspect.Name | Suspect.Age.Clean | Suspect.Gender.Clean | Suspect.Race.Clean | Crime.Category |
|---|---|---|---|---|---|---|---|---|---|
| VIC00642 | Robert Torres | 51 | Unknown | SUS00281 | Barbara Thomas | 51 | Male | Asian | Assault & Battery |
| VIC00262 | John Martin | 50 | Unknown | SUS00376 | Barbara Harris | 46 | Other | Black | Burglary / B&E |
| VIC00518 | Richard Hill | 29 | Other | SUS00560 | Richard Scott | 19 | Female | Asian | Other |
| VIC00243 | Susan Young | 50 | Unknown | SUS00468 | Michael Thomas | 46 | Male | Black | Property Damage |
| VIC00512 | Thomas Thomas | 51 | Male | SUS00751 | Thomas Jackson | 75 | Female | White | Domestic Violence |
| VIC00473 | Anthony Wilson | 15 | Unknown | SUS00454 | James Lee | 73 | Unknown | White | Burglary / B&E |
| VIC00429 | Mary Walker | 72 | Female | SUS00623 | Carol Harris | 58 | Female | Unknown | Robbery |
| VIC00904 | David Torres | 50 | Female | SUS00533 | Jennifer Taylor | 73 | Male | White | Homicide / Murder |
missing_summary <- data %>%
summarise(across(everything(), ~sum(is.na(.)))) %>%
pivot_longer(everything(), names_to = "Variabel", values_to = "Jumlah_Missing") %>%
arrange(desc(Jumlah_Missing))
knitr::kable(missing_summary, caption = "Jumlah nilai hilang pada dataset akhir")
| Variabel | Jumlah_Missing |
|---|---|
| Victim.ID | 0 |
| Victim.Name | 0 |
| Victim.Age.Clean | 0 |
| Victim.Gender.Clean | 0 |
| Suspect.ID | 0 |
| Suspect.Name | 0 |
| Suspect.Age.Clean | 0 |
| Suspect.Gender.Clean | 0 |
| Suspect.Race.Clean | 0 |
| Crime.Category | 0 |
Nilai hilang pada dataset akhir terutama terdapat pada Victim.ID, Victim.Name, Suspect.ID, dan Suspect.Name. Variabel usia, gender, ras tersangka, dan kategori kejahatan tidak memiliki nilai kosong pada data akhir yang digunakan dalam analisis ini.
age_check <- data %>%
summarise(
Usia_Korban_Min = min(Victim.Age.Clean, na.rm = TRUE),
Usia_Korban_Maks = max(Victim.Age.Clean, na.rm = TRUE),
Usia_Tersangka_Min = min(Suspect.Age.Clean, na.rm = TRUE),
Usia_Tersangka_Maks = max(Suspect.Age.Clean, na.rm = TRUE)
)
knitr::kable(age_check, caption = "Rentang usia setelah cleaning")
| Usia_Korban_Min | Usia_Korban_Maks | Usia_Tersangka_Min | Usia_Tersangka_Maks |
|---|---|---|---|
| 10 | 90 | 15 | 75 |
age_summary <- data %>%
summarise(
Rata_rata_Usia_Korban = mean(Victim.Age.Clean, na.rm = TRUE),
SD_Usia_Korban = sd(Victim.Age.Clean, na.rm = TRUE),
Median_Usia_Korban = median(Victim.Age.Clean, na.rm = TRUE),
Rata_rata_Usia_Tersangka = mean(Suspect.Age.Clean, na.rm = TRUE),
SD_Usia_Tersangka = sd(Suspect.Age.Clean, na.rm = TRUE),
Median_Usia_Tersangka = median(Suspect.Age.Clean, na.rm = TRUE)
)
knitr::kable(round(age_summary, 2), caption = "Ringkasan statistik usia")
| Rata_rata_Usia_Korban | SD_Usia_Korban | Median_Usia_Korban | Rata_rata_Usia_Tersangka | SD_Usia_Tersangka | Median_Usia_Tersangka |
|---|---|---|---|---|---|
| 49.89 | 21.04 | 50 | 45.53 | 14.87 | 46 |
Rata-rata usia korban berada di sekitar 49,89 tahun, sedangkan rata-rata usia tersangka sekitar 45,53 tahun. Median usia korban adalah 50 tahun dan median usia tersangka 46 tahun.
ggplot(data, aes(x = Victim.Age.Clean)) +
geom_histogram(binwidth = 5, boundary = 0, color = "white") +
labs(title = "Distribusi Usia Korban", x = "Usia korban", y = "Frekuensi") +
theme_minimal()
ggplot(data, aes(x = Suspect.Age.Clean)) +
geom_histogram(binwidth = 5, boundary = 0, color = "white") +
labs(title = "Distribusi Usia Tersangka", x = "Usia tersangka", y = "Frekuensi") +
theme_minimal()
age_long <- data %>%
select(Victim.Age.Clean, Suspect.Age.Clean) %>%
pivot_longer(everything(), names_to = "Kelompok", values_to = "Usia")
ggplot(age_long, aes(x = Kelompok, y = Usia)) +
geom_boxplot() +
labs(title = "Perbandingan Sebaran Usia", x = NULL, y = "Usia") +
theme_minimal()
victim_gender <- data %>%
count(Victim.Gender.Clean, name = "Frekuensi") %>%
mutate(Persentase = round(Frekuensi / sum(Frekuensi) * 100, 2)) %>%
arrange(desc(Frekuensi))
knitr::kable(victim_gender, caption = "Distribusi jenis kelamin korban")
| Victim.Gender.Clean | Frekuensi | Persentase |
|---|---|---|
| Male | 1824 | 34.75 |
| Female | 1683 | 32.06 |
| Unknown | 1382 | 26.33 |
| Other | 360 | 6.86 |
ggplot(victim_gender, aes(x = reorder(Victim.Gender.Clean, Frekuensi), y = Frekuensi)) +
geom_col() +
coord_flip() +
labs(title = "Distribusi Jenis Kelamin Korban", x = "Jenis kelamin", y = "Frekuensi") +
theme_minimal()
Kategori Male merupakan kategori korban dengan frekuensi terbesar, diikuti Female, Unknown, dan Other.
suspect_gender <- data %>%
count(Suspect.Gender.Clean, name = "Frekuensi") %>%
mutate(Persentase = round(Frekuensi / sum(Frekuensi) * 100, 2)) %>%
arrange(desc(Frekuensi))
knitr::kable(suspect_gender, caption = "Distribusi jenis kelamin tersangka")
| Suspect.Gender.Clean | Frekuensi | Persentase |
|---|---|---|
| Unknown | 1735 | 33.05 |
| Female | 1645 | 31.34 |
| Male | 1554 | 29.61 |
| Other | 315 | 6.00 |
ggplot(suspect_gender, aes(x = reorder(Suspect.Gender.Clean, Frekuensi), y = Frekuensi)) +
geom_col() +
coord_flip() +
labs(title = "Distribusi Jenis Kelamin Tersangka", x = "Jenis kelamin", y = "Frekuensi") +
theme_minimal()
Pada data akhir, kategori Unknown menjadi kategori jenis kelamin tersangka dengan frekuensi terbesar.
race_summary <- data %>%
count(Suspect.Race.Clean, name = "Frekuensi") %>%
mutate(Persentase = round(Frekuensi / sum(Frekuensi) * 100, 2)) %>%
arrange(desc(Frekuensi))
knitr::kable(race_summary, caption = "Distribusi ras tersangka")
| Suspect.Race.Clean | Frekuensi | Persentase |
|---|---|---|
| Unknown | 1967 | 37.47 |
| Black | 780 | 14.86 |
| Hispanic | 745 | 14.19 |
| White | 712 | 13.56 |
| Asian | 706 | 13.45 |
| Other | 339 | 6.46 |
ggplot(race_summary, aes(x = reorder(Suspect.Race.Clean, Frekuensi), y = Frekuensi)) +
geom_col() +
coord_flip() +
labs(title = "Distribusi Ras Tersangka", x = "Ras", y = "Frekuensi") +
theme_minimal()
Kategori Unknown memiliki frekuensi terbesar pada variabel ras tersangka. Karena kategori ini cukup besar, interpretasi perbandingan antar kelompok ras perlu dilakukan secara hati-hati.
crime_summary <- data %>%
count(Crime.Category, name = "Frekuensi") %>%
mutate(Persentase = round(Frekuensi / sum(Frekuensi) * 100, 2)) %>%
arrange(desc(Frekuensi))
knitr::kable(crime_summary, caption = "Distribusi kategori kejahatan")
| Crime.Category | Frekuensi | Persentase |
|---|---|---|
| Assault & Battery | 963 | 18.35 |
| Fraud & Scam | 457 | 8.71 |
| Arson | 369 | 7.03 |
| Drug Offense | 362 | 6.90 |
| Theft / Larceny | 348 | 6.63 |
| Kidnapping | 343 | 6.53 |
| Robbery | 334 | 6.36 |
| Burglary / B&E | 329 | 6.27 |
| Domestic Violence | 329 | 6.27 |
| Cybercrime | 318 | 6.06 |
| DUI / Drunk Driving | 307 | 5.85 |
| Homicide / Murder | 297 | 5.66 |
| Vandalism | 284 | 5.41 |
| Other | 122 | 2.32 |
| Property Damage | 49 | 0.93 |
| Sexual Assault | 38 | 0.72 |
ggplot(crime_summary, aes(x = reorder(Crime.Category, Frekuensi), y = Frekuensi)) +
geom_col() +
coord_flip() +
labs(title = "Distribusi Kategori Kejahatan", x = "Kategori kejahatan", y = "Frekuensi") +
theme_minimal()
Kategori Assault & Battery merupakan kategori dengan jumlah catatan terbanyak, yaitu 963 observasi. Kategori dengan jumlah paling sedikit adalah Sexual Assault, yaitu 38 observasi.
cor_age <- cor(data$Victim.Age.Clean, data$Suspect.Age.Clean, use = "complete.obs")
cor_age
## [1] 0.003080492
Nilai korelasi Pearson antara usia korban dan usia tersangka digunakan hanya untuk melihat kecenderungan hubungan linear sederhana.
ggplot(data, aes(x = Victim.Age.Clean, y = Suspect.Age.Clean)) +
geom_point(alpha = 0.25) +
geom_smooth(method = "lm", se = FALSE) +
labs(title = "Hubungan Usia Korban dan Usia Tersangka",
x = "Usia korban", y = "Usia tersangka") +
theme_minimal()
Pada data ini, hubungan linear usia korban dan usia tersangka sangat lemah. Karena analisis yang dilakukan bersifat eksploratif, hasil tersebut tidak digunakan untuk menyatakan adanya hubungan sebab-akibat.
crime_gender <- data %>%
count(Crime.Category, Victim.Gender.Clean) %>%
arrange(Crime.Category, desc(n))
knitr::kable(crime_gender, col.names = c("Kategori Kejahatan", "Gender Korban", "Frekuensi"),
caption = "Tabulasi silang kategori kejahatan dan gender korban")
| Kategori Kejahatan | Gender Korban | Frekuensi |
|---|---|---|
| Arson | Male | 134 |
| Arson | Female | 109 |
| Arson | Unknown | 98 |
| Arson | Other | 28 |
| Assault & Battery | Male | 324 |
| Assault & Battery | Female | 315 |
| Assault & Battery | Unknown | 258 |
| Assault & Battery | Other | 66 |
| Burglary / B&E | Unknown | 117 |
| Burglary / B&E | Female | 98 |
| Burglary / B&E | Male | 91 |
| Burglary / B&E | Other | 23 |
| Cybercrime | Male | 120 |
| Cybercrime | Female | 91 |
| Cybercrime | Unknown | 83 |
| Cybercrime | Other | 24 |
| DUI / Drunk Driving | Male | 99 |
| DUI / Drunk Driving | Female | 95 |
| DUI / Drunk Driving | Unknown | 88 |
| DUI / Drunk Driving | Other | 25 |
| Domestic Violence | Male | 121 |
| Domestic Violence | Unknown | 98 |
| Domestic Violence | Female | 94 |
| Domestic Violence | Other | 16 |
| Drug Offense | Female | 134 |
| Drug Offense | Male | 125 |
| Drug Offense | Unknown | 79 |
| Drug Offense | Other | 24 |
| Fraud & Scam | Male | 166 |
| Fraud & Scam | Female | 144 |
| Fraud & Scam | Unknown | 117 |
| Fraud & Scam | Other | 30 |
| Homicide / Murder | Female | 104 |
| Homicide / Murder | Male | 101 |
| Homicide / Murder | Unknown | 72 |
| Homicide / Murder | Other | 20 |
| Kidnapping | Female | 119 |
| Kidnapping | Male | 116 |
| Kidnapping | Unknown | 81 |
| Kidnapping | Other | 27 |
| Other | Female | 44 |
| Other | Male | 42 |
| Other | Unknown | 30 |
| Other | Other | 6 |
| Property Damage | Male | 20 |
| Property Damage | Unknown | 17 |
| Property Damage | Female | 9 |
| Property Damage | Other | 3 |
| Robbery | Male | 115 |
| Robbery | Female | 110 |
| Robbery | Unknown | 85 |
| Robbery | Other | 24 |
| Sexual Assault | Female | 19 |
| Sexual Assault | Male | 12 |
| Sexual Assault | Unknown | 6 |
| Sexual Assault | Other | 1 |
| Theft / Larceny | Male | 134 |
| Theft / Larceny | Female | 101 |
| Theft / Larceny | Unknown | 92 |
| Theft / Larceny | Other | 21 |
| Vandalism | Male | 104 |
| Vandalism | Female | 97 |
| Vandalism | Unknown | 61 |
| Vandalism | Other | 22 |
ggplot(crime_gender, aes(x = reorder(Crime.Category, n), y = n,
fill = Victim.Gender.Clean)) +
geom_col(position = "stack") +
coord_flip() +
labs(title = "Kategori Kejahatan Menurut Gender Korban",
x = "Kategori kejahatan", y = "Frekuensi", fill = "Gender korban") +
theme_minimal()
Salah satu bentuk transformasi yang dapat digunakan adalah one-hot encoding. Setiap kategori jenis kelamin dibuat menjadi indikator 0 dan 1.
data_encoded <- data %>%
mutate(
Victim_Gender_Male = as.integer(Victim.Gender.Clean == "Male"),
Victim_Gender_Female = as.integer(Victim.Gender.Clean == "Female"),
Victim_Gender_Unknown = as.integer(Victim.Gender.Clean == "Unknown"),
Victim_Gender_Other = as.integer(Victim.Gender.Clean == "Other")
)
knitr::kable(head(data_encoded %>%
select(Victim.Gender.Clean, Victim_Gender_Male,
Victim_Gender_Female, Victim_Gender_Unknown,
Victim_Gender_Other), 8),
caption = "Contoh hasil one-hot encoding gender korban")
| Victim.Gender.Clean | Victim_Gender_Male | Victim_Gender_Female | Victim_Gender_Unknown | Victim_Gender_Other |
|---|---|---|---|---|
| Unknown | 0 | 0 | 1 | 0 |
| Unknown | 0 | 0 | 1 | 0 |
| Other | 0 | 0 | 0 | 1 |
| Unknown | 0 | 0 | 1 | 0 |
| Male | 1 | 0 | 0 | 0 |
| Unknown | 0 | 0 | 1 | 0 |
| Female | 0 | 1 | 0 | 0 |
| Female | 0 | 1 | 0 | 0 |
Untuk memudahkan pembacaan deskriptif, usia dapat dikelompokkan menjadi beberapa interval.
data_encoded <- data_encoded %>%
mutate(
Victim_Age_Group = cut(
Victim.Age.Clean,
breaks = c(0, 17, 30, 45, 60, Inf),
labels = c("0-17", "18-30", "31-45", "46-60", ">60"),
right = TRUE
),
Suspect_Age_Group = cut(
Suspect.Age.Clean,
breaks = c(0, 17, 30, 45, 60, Inf),
labels = c("0-17", "18-30", "31-45", "46-60", ">60"),
right = TRUE
)
)
knitr::kable(head(data_encoded %>%
select(Victim.Age.Clean, Victim_Age_Group,
Suspect.Age.Clean, Suspect_Age_Group), 8),
caption = "Contoh pengelompokan usia")
| Victim.Age.Clean | Victim_Age_Group | Suspect.Age.Clean | Suspect_Age_Group |
|---|---|---|---|
| 51 | 46-60 | 51 | 46-60 |
| 50 | 46-60 | 46 | 46-60 |
| 29 | 18-30 | 19 | 18-30 |
| 50 | 46-60 | 46 | 46-60 |
| 51 | 46-60 | 75 | >60 |
| 15 | 0-17 | 73 | >60 |
| 72 | >60 | 58 | 46-60 |
| 50 | 46-60 | 73 | >60 |
Z-score digunakan untuk mengubah usia ke skala standar sehingga nilai dapat dibandingkan berdasarkan jaraknya terhadap rata-rata kelompok.
data_encoded <- data_encoded %>%
mutate(
Victim_Age_Z = as.numeric(scale(Victim.Age.Clean)),
Suspect_Age_Z = as.numeric(scale(Suspect.Age.Clean))
)
knitr::kable(head(data_encoded %>%
select(Victim.Age.Clean, Victim_Age_Z,
Suspect.Age.Clean, Suspect_Age_Z), 10),
digits = 3,
caption = "Contoh hasil standardisasi Z-score")
| Victim.Age.Clean | Victim_Age_Z | Suspect.Age.Clean | Suspect_Age_Z |
|---|---|---|---|
| 51 | 0.053 | 51 | 0.368 |
| 50 | 0.005 | 46 | 0.032 |
| 29 | -0.993 | 19 | -1.784 |
| 50 | 0.005 | 46 | 0.032 |
| 51 | 0.053 | 75 | 1.982 |
| 15 | -1.659 | 73 | 1.847 |
| 72 | 1.051 | 58 | 0.839 |
| 50 | 0.005 | 73 | 1.847 |
| 55 | 0.243 | 26 | -1.313 |
| 10 | -1.896 | 46 | 0.032 |
Hasil eksplorasi menunjukkan bahwa data akhir telah memiliki variabel analisis yang lebih terarah dibandingkan data awal. Usia korban memiliki rata-rata sekitar 49,89 tahun, sedangkan usia tersangka sekitar 45,53 tahun. Distribusi jenis kelamin menunjukkan bahwa kategori Male paling banyak pada korban, sedangkan kategori Unknown paling banyak pada tersangka.
Untuk ras tersangka, kategori Unknown merupakan kategori dengan jumlah terbesar. Hal ini penting diperhatikan karena data yang tidak diketahui dapat memengaruhi perbandingan antar kelompok. Pada kategori kejahatan, Assault & Battery menjadi kategori yang paling sering tercatat.
Korelasi usia korban dan usia tersangka sangat dekat dengan nol, sehingga pola linear yang kuat tidak terlihat pada dataset ini. Temuan tersebut hanya merupakan gambaran eksploratif dan tidak dapat digunakan sebagai bukti hubungan sebab-akibat.
Berdasarkan eksplorasi data yang telah dilakukan, dapat disimpulkan bahwa:
Analisis berikutnya dapat dikembangkan dengan menambahkan informasi waktu dan lokasi apabila variabel tersebut tersedia pada data mentah. Analisis juga dapat diperluas menggunakan tabulasi silang, uji statistik yang sesuai, atau model prediktif. Sebelum melakukan analisis lanjutan, kualitas kategori Unknown dan kelengkapan identitas tetap perlu diperhatikan.
Seluruh langkah analisis pada laporan ini ditulis menggunakan R
Markdown sehingga kode dapat dijalankan kembali. File Excel
Crime_Incidents_Clean Kelompok Mantull.xlsx perlu
ditempatkan pada folder yang sama dengan file .Rmd sebelum
proses Knit.
## Analisis dibuat dengan R dan R Markdown.