File size: 7,340 Bytes
6f10462 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import csv
import os.path
import pandas as pd
import re
import numpy as np
import math
def kategorikan(amar):
if amar is None:
return None
a = amar.lower().strip()
if ("seumur hidup" in a):
return "penjara seumur hidup"
# 1. Pidana Penjara
if ("pidana penjara" in a) or ("kurungan" in a) or ("subsider penjara" in a):
return "pidana penjara"
# 2. Pidana Denda
if ("pidana denda" in a) or ("subsider denda" in a):
return "pidana denda"
# 3. Hukuman Mati
if "pidana mati" in a:
return "pidana mati"
# 4. Bebas Dakwaan
if ("bebas dari dakwaan" in a) or ("lepas dari tuntutan" in a) \
or ("membebaskan" in a and "dakwaan" in a):
return "bebas dakwaan"
# 5. Bebas Bersyarat
if ("pidana bersyarat" in a) or ("restorative justice" in a) \
or ("dikembalikan kepada orang tua" in a) \
or ("pidana tambahan" in a) \
or ("lain-lain" in a) or ("lain lain" in a) or ("lain-lain" in a) \
or ("penghentian pemeriksaan perkara" in a):
return "bebas bersyarat"
# 6. Terdakwa meninggal → drop (return None)
if "meninggal" in a:
return None
# 7. Tidak dikenali → drop
return None
# Fungsi ekstraksi lama penjara (bulan)
def extract_penjara(text):
if pd.isna(text):
return None
# cari tahun
tahun = re.search(r'(\d+)\s*\(.*?\)\s*tahun', text, re.IGNORECASE)
tahun = int(tahun.group(1)) if tahun else 0
# cari bulan
bulan = re.search(r'(\d+)\s*\(.*?\)\s*bulan', text, re.IGNORECASE)
bulan = int(bulan.group(1)) if bulan else 0
return tahun * 12 + bulan # total bulan
# Fungsi ekstraksi nilai denda
def extract_denda(text):
if pd.isna(text):
return None
# cari angka setelah "pidana denda sebesar rp"
match = re.search(r'pidana denda\s*(sebesar|sejumlah|retribusi+\s+sebesar|restribusi+\s+sebesar)?\s*(?:rp\.?\s*){1,2}([\d.]+)', text, re.IGNORECASE)
#print(match)
if match:
# hapus titik sebagai pemisah ribuan, ubah jadi integer
return int(match.group(2).replace('.', ''))
return None
# Fungsi utama untuk apply ke DataFrame
def proses_amar(row):
cat = row["kategori_bersih"] # kolom kategori utama: pidana_penjara / pidana_denda / dll
text = row["catatan_amar"]
if cat == "pidana penjara":
return extract_penjara(text), None
elif cat == "pidana denda":
return None, extract_denda(text)
else:
# kategori lain → kosong
return None, None
def ringkasan(df):
# hitung jumlah kasus per tindak pidana
total_kasus = len(df)
# fungsi bantu untuk menghitung persentase kategori hukuman
def pct_cat(subdf, cat):
return round(100 * (subdf['kategori_bersih'] == cat).sum() / len(subdf), 3)
# agregasi
summary = []
for tp, group in df.groupby('kata_kunci'):
rata_penjara = round(group.loc[group['kategori_bersih']=='pidana penjara', 'lama_penjara'].mean(), 1)
rata_denda = round(group.loc[group['kategori_bersih']=='pidana denda', 'banyak_denda'].mean(), 0)
pct_penjara = pct_cat(group, 'pidana penjara')
pct_seumur = pct_cat(group, 'penjara seumur hidup')
pct_denda = pct_cat(group, 'pidana denda')
pct_bebas_bersyarat = pct_cat(group, 'bebas bersyarat')
pct_bebas_dakwaan = pct_cat(group, 'bebas dakwaan')
pct_mati = pct_cat(group, 'pidana mati')
pct_kasus = round(100 * len(group) / total_kasus, 3)
summary.append({
'tindak pidana': tp,
'rata-rata penjara': rata_penjara,
'rata-rata denda': rata_denda,
'penjara': f"{pct_penjara}",
'penjara seumur hidup': f"{pct_seumur}",
'denda': f"{pct_denda}",
'bebas bersyarat': f"{pct_bebas_bersyarat}",
'bebas dakwaan': f"{pct_bebas_dakwaan}",
'hukuman mati': f"{pct_mati}",
'kontribusi kasus': f"{pct_kasus}"
})
# buat DataFrame
tabel_ringkasan = pd.DataFrame(summary)
WEIGHTS = {
'hukuman mati': 10.0,
'penjara seumur hidup': 8.0,
'penjara': 5.0,
'denda': 1.5,
'bebas bersyarat': -1.0,
'bebas dakwaan': -2.0
}
def to_float(x):
if x is None:
return 0.0
try:
v = float(str(x).replace('%','').replace(',',''))
if math.isnan(v):
return 0.0
return v
except:
return 0.0
def hitung_score(row):
hm = to_float(row['hukuman mati'])
sh = to_float(row['penjara seumur hidup'])
pj = to_float(row['penjara'])
dn = to_float(row['denda'])
bb = to_float(row['bebas bersyarat'])
bd = to_float(row['bebas dakwaan'])
base_score = (
hm * WEIGHTS['hukuman mati'] * 1.2 +
sh * WEIGHTS['penjara seumur hidup'] * 1.2 +
pj * WEIGHTS['penjara'] * 1.0 +
dn * WEIGHTS['denda'] * 1.0 +
bb * WEIGHTS['bebas bersyarat'] * 2.0 +
bd * WEIGHTS['bebas dakwaan'] * 2.0
)
rata_penjara = to_float(row.get('rata-rata penjara', 0))
penjara_boost = rata_penjara * 4
rata_denda = to_float(row.get('rata-rata denda', 0))
denda_boost = np.log10(rata_denda + 10) * 8 if rata_denda > 0 else 0
return base_score + penjara_boost + denda_boost
# --- LANGKAH 1: hitung skor sementara tanpa menyimpan ---
semua_skor = tabel_ringkasan.apply(hitung_score, axis=1).tolist()
# --- LANGKAH 2: hitung threshold otomatis ---
p33 = np.percentile(semua_skor, 33)
p66 = np.percentile(semua_skor, 66)
# --- LANGKAH 3: fungsi final klasifikasi ---
def klasifikasi_pidana(row):
score = hitung_score(row) # tidak disimpan
#print(f"{row['tindak Pidana']}: score={score:.2f}")
if score <= p33:
return "light"
elif score <= p66:
return "moderate"
else:
return "serious"
# --- LANGKAH 4: simpan hanya kategori ---
tabel_ringkasan['kategori_pidana'] = tabel_ringkasan.apply(klasifikasi_pidana, axis=1)
return tabel_ringkasan
def normalize_ringkasan(df):
numeric_cols = [
"penjara",
"penjara seumur hidup",
"denda",
"bebas bersyarat",
"bebas dakwaan",
"hukuman mati",
"kontribusi kasus"
]
for col in numeric_cols:
df[col] = pd.to_numeric(df[col], errors="coerce").fillna(0)
return df
def table_summary(df):
df["kategori_bersih"] = df["amar_lainnya"].apply(kategorikan)
# hapus baris yang tidak masuk 5 kategori utama
df = df[df["kategori_bersih"].notna()]
# Terapkan ke DataFrame
df["lama_penjara"], df["banyak_denda"] = zip(*df.apply(proses_amar, axis=1))
tabel = normalize_ringkasan(ringkasan(df))
return tabel
|