Banyak orang bilang, "belajar yang rajin, nanti nilainya bagus." Tapi apa itu kelihatan di data? Di artikel ini kami bedah data nilai siswa sungguhan pakai Python, dari cek data sampai hitung peluang. Alurnya mengikuti contoh EDA dataset Iris oleh Alex Lopez: tiap langkah ada kode, hasil, lalu penjelasannya.
Ringkasan hasil:
- Waktu belajar hampir nggak berhubungan dengan nilai akhir (r = 0,10).
- Nilai periode 1 justru kuat memprediksi nilai akhir (r = 0,80).
- Siswa dengan nilai periode 1 di atas 10 punya peluang lulus 90%, sedangkan yang di bawah 10 hanya 27%.
Daftar isi
- Dataset
- Cek data
- Statistika deskriptif
- Visualisasi
- Analisis bivariat
- Probabilitas
- Refleksi dan kesimpulan
1. Dataset
Kami pakai dataset Student Performance dari UCI yang ada di Kaggle, file student-mat.csv. Isinya 395 siswa sekolah menengah di Portugal yang ikut kelas matematika, dikumpulkan lewat laporan sekolah dan kuesioner (Cortez & Silva, 2008).
Dua istilah dasar supaya nggak bingung:
- Populasi: semua siswa yang ingin kita ketahui.
- Sampel: 395 siswa yang datanya benar-benar kita punya. Kesimpulan kita cuma berlaku kuat untuk sampel ini.
Dari 33 kolom, kami pakai enam:
| Kolom | Arti | Jenis data |
|---|---|---|
studytime |
Waktu belajar per minggu: 1 = <2 jam, 2 = 2-5 jam, 3 = 5-10 jam, 4 = >10 jam | Kategori berurutan |
failures |
Berapa kali pernah gagal | Angka |
absences |
Jumlah absen | Angka |
G1 |
Nilai periode 1 (0-20) | Angka |
G2 |
Nilai periode 2 (0-20) | Angka |
G3 |
Nilai akhir (0-20) | Angka |
Catatan: studytime itu kelompok, bukan jam belajar yang tepat. Ini akan berpengaruh ke hasil nanti.
2. Cek data
Langkah pertama: import library, baca data, lalu lihat ukuran dan isinya.
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
os.makedirs("gambar", exist_ok=True)
sns.set_theme(style="whitegrid")
df = pd.read_csv("student-mat.csv")
print(df.shape)
print(df.isnull().sum().sum())
df[["studytime", "failures", "absences", "G1", "G2", "G3"]].head(8)
Hasil: 395 baris, 33 kolom, dan 0 data kosong. Jadi datanya bersih dan siap dianalisis. Delapan baris pertama:
| studytime | failures | absences | G1 | G2 | G3 |
|---|---|---|---|---|---|
| 2 | 0 | 6 | 5 | 6 | 6 |
| 2 | 0 | 4 | 5 | 5 | 6 |
| 2 | 3 | 10 | 7 | 8 | 10 |
| 3 | 0 | 2 | 15 | 14 | 15 |
| 2 | 0 | 4 | 6 | 10 | 10 |
| 2 | 0 | 10 | 15 | 15 | 15 |
| 2 | 0 | 0 | 12 | 12 | 11 |
| 2 | 0 | 6 | 6 | 5 | 6 |
3. Statistika deskriptif
Statistika deskriptif itu cara meringkas data jadi beberapa angka. Kami mulai dari nilai akhir (G3).
g3 = df["G3"]
print(g3.mean(), g3.median(), g3.mode().tolist())
print(g3.max() - g3.min(), g3.var(), g3.std())
print((g3 == 0).sum())
Hasil:
| Ukuran | Nilai | Arti singkatnya |
|---|---|---|
| Mean | 10,42 | Rata-rata nilai akhir |
| Median | 11 | Nilai tengah kalau diurutkan |
| Modus | 10 | Nilai yang paling sering muncul |
| Rentang | 20 | Selisih nilai tertinggi dan terendah |
| Varians | 20,99 | Ukuran seberapa menyebar nilai |
| Simpangan baku | 4,58 | Rata-rata "jarak" nilai dari mean |
Artinya: rata-rata siswa dapat sekitar 10 dari 20, dan nilainya cukup beragam (simpangan baku sekitar 4-5 poin). Perhatikan bahwa median (11) lebih tinggi dari mean (10,42). Itu tanda ada nilai sangat kecil yang menarik rata-rata turun. Waktu kami cek, ternyata ada 38 siswa dengan nilai akhir 0. Datanya nggak menjelaskan kenapa, jadi kami cuma mencatatnya.
Sekarang kita cek: apakah yang belajarnya lebih lama nilainya lebih tinggi?
df.groupby("studytime")["G3"].agg(["count", "mean", "median"])
Hasil:
| studytime | Jumlah siswa | Mean G3 | Median G3 |
|---|---|---|---|
| 1 (<2 jam) | 105 | 10,05 | 10 |
| 2 (2-5 jam) | 198 | 10,17 | 11 |
| 3 (5-10 jam) | 65 | 11,40 | 12 |
| 4 (>10 jam) | 27 | 11,26 | 12 |
Artinya: ada kenaikan, tapi kecil. Selisih terbesarnya cuma sekitar 1,3 poin.
4. Visualisasi
Angka lebih gampang dipahami kalau digambar. Pertama, histogram nilai akhir:
plt.figure(figsize=(7, 4.5))
plt.hist(g3, bins=range(0, 22), color="#4C78A8", edgecolor="white")
plt.axvline(g3.mean(), color="red", linestyle="--", label=f"Mean = {g3.mean():.2f}")
plt.axvline(g3.median(), color="green", linestyle="-", label=f"Median = {g3.median():.0f}")
plt.title("Sebaran Nilai Akhir (G3)")
plt.xlabel("Nilai akhir (0-20)")
plt.ylabel("Jumlah siswa")
plt.legend()
plt.tight_layout()
plt.savefig("gambar/1_histogram_g3.png", dpi=150)
plt.show()
Artinya: kebanyakan siswa ada di tengah sampai kanan, tapi ada tumpukan kecil di angka 0. Itu yang menarik mean ke bawah.
Kedua, boxplot nilai akhir untuk tiap kelompok waktu belajar:
plt.figure(figsize=(7, 4.5))
sns.boxplot(x="studytime", y="G3", data=df, hue="studytime", palette="Set2", legend=False)
plt.xticks([0, 1, 2, 3], ["<2 jam", "2-5 jam", "5-10 jam", ">10 jam"])
plt.title("Nilai Akhir Berdasarkan Waktu Belajar Mingguan")
plt.xlabel("Waktu belajar per minggu")
plt.ylabel("Nilai akhir (G3)")
plt.tight_layout()
plt.savefig("gambar/2_boxplot_studytime.png", dpi=150)
plt.show()
Artinya: garis tengah kotak (median) naik sedikit untuk yang belajar lebih lama, tapi kotaknya banyak yang tumpang tindih. Jadi bedanya nggak tegas. Titik-titik bulat di angka 0 adalah siswa bernilai 0 tadi.
5. Analisis bivariat
Analisis bivariat artinya melihat hubungan dua variabel. Ukurannya adalah korelasi Pearson (r), nilainya dari -1 sampai +1:
- mendekati +1: naik bareng, hubungannya kuat
- mendekati 0: nyaris nggak ada hubungan
- mendekati -1: yang satu naik, yang lain turun
print(df["studytime"].corr(df["G3"]))
print(df["absences"].corr(df["G3"]))
print(df["G1"].corr(df["G3"]))
Hasil:
| Pasangan variabel | r | Kekuatan |
|---|---|---|
studytime dan G3
|
0,10 | Sangat lemah |
absences dan G3
|
0,03 | Hampir nol |
G1 dan G3
|
0,80 | Kuat |
Untuk melihat semua korelasi sekaligus, kita pakai heatmap:
kolom = ["studytime", "absences", "failures", "G1", "G2", "G3"]
plt.figure(figsize=(7, 5.5))
sns.heatmap(df[kolom].corr(), annot=True, fmt=".2f", cmap="coolwarm", vmin=-1, vmax=1)
plt.title("Korelasi Antar Variabel")
plt.tight_layout()
plt.savefig("gambar/4_heatmap_korelasi.png", dpi=150)
plt.show()
Hubungan yang paling menarik adalah G1 dan G3, jadi kita gambar scatter plot beserta garis regresinya:
r = df["G1"].corr(df["G3"])
slope, intercept = np.polyfit(df["G1"], df["G3"], 1)
print(r, r ** 2, intercept, slope)
plt.figure(figsize=(7, 5))
sns.regplot(x="G1", y="G3", data=df, x_jitter=0.2, y_jitter=0.2,
scatter_kws={"alpha": 0.5, "s": 25},
line_kws={"color": "red"})
plt.title(f"Nilai Periode 1 (G1) vs Nilai Akhir (G3), r = {r:.2f}")
plt.xlabel("G1")
plt.ylabel("G3")
plt.tight_layout()
plt.savefig("gambar/3_scatter_g1_g3.png", dpi=150)
plt.show()
Hasil: r = 0,80, R² = 0,64, dan garis regresinya G3 = -1,65 + 1,11 × G1.
Artinya:
- Tiap G1 naik 1 poin, G3 rata-rata ikut naik sekitar 1,1 poin. Contoh: G1 = 12 diprediksi G3 sekitar 11,6.
- R² = 0,64 berarti sekitar 64% variasi nilai akhir bisa dijelaskan oleh nilai periode 1.
- Deretan titik di G3 = 0 "merusak" pola. Kalau 38 siswa itu dibuang, r naik dari 0,80 jadi 0,89.
Korelasi bukan sebab-akibat. G1 tinggi nggak menyebabkan G3 tinggi. Bisa jadi keduanya sama-sama dipengaruhi hal lain, misalnya kemampuan dasar. Sebaliknya, korelasi waktu belajar yang lemah belum tentu berarti belajar itu sia-sia, karena studytime cuma empat kelompok yang diisi sendiri oleh siswa.
6. Probabilitas
Sekarang kita lihat dari sisi peluang. Kita tentukan dua kejadian (batas lulus kami tetapkan 10 dari 20):
-
A: siswa lulus (
G3 >= 10) -
B: siswa sudah punya
G1 >= 10
lulus = df["G3"] >= 10
g1_bagus = df["G1"] >= 10
print(lulus.mean(), g1_bagus.mean(), (lulus & g1_bagus).mean())
print(lulus[g1_bagus].mean(), lulus[~g1_bagus].mean())
Hasil (ambil satu siswa secara acak dari 395):
| Peluang | Perhitungan | Nilai |
|---|---|---|
| P(A) | 265 / 395 | 0,67 |
| P(B) | 253 / 395 | 0,64 |
| P(A dan B) | 227 / 395 | 0,57 |
| P(A | B) | 0,57 / 0,64 | 0,90 |
| P(A | bukan B) | 38 / 142 | 0,27 |
Peluang bersyarat artinya peluang A kalau kita sudah tahu B terjadi. Jadi kalau G1 seseorang sudah 10 ke atas, peluang lulusnya naik dari 67% jadi 90%. Kalau G1-nya di bawah 10, peluang lulusnya cuma 27%.
Uji independen. Dua kejadian disebut independen kalau P(A dan B) = P(A) × P(B). Di sini P(A) × P(B) = 0,67 × 0,64 = 0,43, padahal P(A dan B) sebenarnya 0,57. Angkanya jauh beda, jadi A dan B tidak independen: nilai awal memang memberi informasi soal kelulusan.
Sebagai pembanding, kami hitung juga untuk siswa yang "rajin belajar" (studytime 3 atau 4, jumlahnya 92 siswa). Peluang lulus mereka 0,75, sedangkan yang tidak rajin 0,65. Ada bedanya, tapi jauh lebih kecil dari pengaruh G1.
7. Refleksi dan kesimpulan
Yang kami pelajari:
- Angka baru berarti setelah ditafsirkan. Mean 10,42 saja nggak cerita apa-apa sampai kami bandingkan dengan median dan menemukan 38 siswa bernilai 0.
- Hasil yang nggak sesuai dugaan itu wajar. Kami kira jam belajar bakal jadi bintang cerita ini, ternyata korelasinya lemah.
- Kami jadi lebih hati-hati memakai kata "menyebabkan". Datanya cuma dari dua sekolah dan satu mata pelajaran, jadi nggak bisa dianggap berlaku untuk semua siswa.
Kesimpulan: di data 395 siswa ini, nilai periode pertama jauh lebih bisa menebak nilai akhir (r = 0,80) daripada waktu belajar (r = 0,10). Ini bukan berarti belajar nggak penting, karena ukuran waktu belajar di data ini kasar dan masih banyak faktor yang belum kami periksa. Langkah berikutnya yang menarik adalah melihat pengaruh failures (korelasinya -0,36 dengan G3).
Kode lengkap dan datanya ada di GitHub kami: GANTI_DENGAN_LINK_REPO_GITHUB (file analisis_nilai_siswa.py dan student-mat.csv).
Penggunaan AI
Kami memakai Deepseek untuk membantu menyusun kerangka artikel dan menulis kode Python. Semua kode kami jalankan sendiri, angka-angkanya kami cek ulang dari output Python, dan isi artikel kami sesuaikan dengan pemahaman kami.
Referensi
- Student Alcohol Consumption (UCI Machine Learning). Kaggle. https://www.kaggle.com/datasets/uciml/student-alcohol-consumption
- Lopez, A. (StatsBio). [Python] - Exploratory Data Analysis example, Iris dataset. Medium. https://medium.com/@StatsBio/exploratory-data-analysis-example-iris-dataset-b224c26ad448
- Materi kuliah Statistika & Probabilitas (Introduction, Descriptive Statistics, Bivariate Analysis, Basic Probability).




Top comments (1)