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