Angka korelasi sudah tiga chapter menjadi alat kerja andalan kita — dipakai menemukan pita harga di analisis bivariat, lalu dibongkar perbaikannya saat variabel ketiga masuk. Sekarang saatnya membedah alat itu sendiri: apa yang sebenarnya dihitung oleh korelasi, kapan Pearson layak dipakai dan kapan harus pindah ke Spearman, bagaimana membaca matriks korelasi dalam bentuk heatmap, dan di mana batas tafsirnya. Pemahaman formal seperti ini penting karena korelasi adalah angka yang paling sering dikutip, dan sekaligus paling sering disalahartikan, dalam laporan data.
Rumus di Balik Angka Pearson #
Korelasi Pearson mengukur seberapa rapat pasangan nilai mengikuti satu garis lurus. Rumusnya bisa ditulis dalam bentuk skor-z: ubah setiap nilai menjadi jaraknya dari rata-rata, dalam satuan simpangan baku, lalu rata-ratakan hasil kali kedua skor:
z_x = (x - mean(x)) / std(x)
z_y = (y - mean(y)) / std(y)
r = jumlah(z_x * z_y) / (n - 1)Intuisinya: pasangan yang sama-sama di atas rata-rata (atau sama-sama di bawah) menghasilkan hasil kali positif, sedangkan pasangan yang berlawanan menghasilkan negatif — r adalah rata-rata seluruh “suara” itu. Kita hitung manual untuk enam hari operasional Toko Kopi Kita:
import pandas as pd
hari = pd.DataFrame({
"pengunjung": [120, 150, 180, 200, 230, 260],
"gelas_terjual": [90, 110, 140, 150, 180, 200],
})
zx = (hari["pengunjung"] - hari["pengunjung"].mean()) / hari["pengunjung"].std()
zy = (hari["gelas_terjual"] - hari["gelas_terjual"].mean()) / hari["gelas_terjual"].std()
r_manual = (zx * zy).sum() / (len(hari) - 1)
r_pandas = hari["pengunjung"].corr(hari["gelas_terjual"])
print("z-x :", zx.round(2).tolist())
print("z-y :", zy.round(2).tolist())
print("r manual :", round(r_manual, 3))
print("r pandas :", round(r_pandas, 3))Output yang Dihasilkan:
z-x : [-1.36, -0.78, -0.19, 0.19, 0.78, 1.36]
z-y : [-1.33, -0.85, -0.12, 0.12, 0.85, 1.33]
r manual : 0.998
r pandas : 0.998Baris demi baris, kode di atas menurunkan rumus secara langsung: zx dan zy mengubah tiap kolom menjadi skor-z, (zx * zy).sum() menjumlahkan hasil kali tiap pasangan, dan pembagian (len(hari) - 1) merata-ratakannya — persis rumus pada blok text. Hasilnya identik dengan corr() dari pandas, karena pandas memakai simpangan baku sampel (n - 1) yang sama dengan perhitungan manual kita. Perhatikan pula pola kedua baris z: hari sepi ber-z negatif di kedua kolom, hari ramai ber-z positif di kedua kolom — hampir semua hasil kali bernilai positif, itulah sumber r yang mendekati 1.
Pearson untuk Garis Lurus, Spearman untuk Urutan #
Pearson punya satu syarat yang sering luput: hubungan yang diukurnya adalah hubungan garis lurus. Ketika hubungan nyata tetapi melengkung, Pearson menilai rendah. Data berikut mencatat delapan barista dan lamanya dilatih berbanding waktu rata-rata menyajikan satu pesanan — penurunan waktu paling deras terjadi di bulan-bulan awal, lalu melandai:
import pandas as pd
from scipy import stats
latihan = pd.DataFrame({
"lama_latihan_bulan": [1, 2, 3, 4, 5, 6, 7, 8],
"waktu_saji_menit": [9.0, 7.6, 6.5, 5.8, 5.3, 5.0, 4.9, 4.85],
})
r_pearson = latihan["lama_latihan_bulan"].corr(latihan["waktu_saji_menit"])
r_spearman = latihan["lama_latihan_bulan"].corr(latihan["waktu_saji_menit"], method="spearman")
print("pandas : pearson", round(r_pearson, 3), "| spearman", round(r_spearman, 3))
stat_p, p_p = stats.pearsonr(latihan["lama_latihan_bulan"], latihan["waktu_saji_menit"])
stat_s, p_s = stats.spearmanr(latihan["lama_latihan_bulan"], latihan["waktu_saji_menit"])
print(f"scipy : pearson r={stat_p:.3f} p={p_p:.2e}")
print(f" spearman r={stat_s:.3f} p={p_s:.2e}")Output yang Dihasilkan:
pandas : pearson -0.924 | spearman -1.0
scipy : pearson r=-0.924 p=1.03e-03
spearman r=-1.000 p=0.00e+00Tiga hal perlu dibaca dari output tersebut:
- Spearman sempurna (-1,0): Spearman tidak memakai nilai mentah, melainkan peringkat. Delapan barista tersusun monoton turun — setiap tambahan bulan latihan selalu mempercepat sajian — sehingga kesesuaian peringkatnya sempurna meski kurvanya melengkung.
- Pearson terpaut (-0,924): Pearson memakai nilai mentah dan “menghukum” pelandaian kurva — pasangan bulan-bulan akhir menjauh dari garis lurus terbaik, sehingga nilainya turun.
- p-value dari scipy: fungsi
pearsonrdanspearmanrmengembalikan pasangan (r, p-value). p Pearson 1,03e-03 berarti peluang melihat hubungan seerat ini pada data yang sesungguhnya tak berhubungan hanya sekitar 0,1%; p Spearman tercetak 0,00e+00 — nilai yang telah jatuh di bawah presisi komputer. Makna p-value ini kita bedah tuntas pada chapter Pengujian Hipotesis dan p-value .
Pilihan praktisnya dirangkum pada tabel berikut:
| Wujud hubungan | Ukuran yang tepat | Alasannya |
|---|---|---|
| Dugaan garis lurus, data bersih | Pearson | mengukur keterikatan nilai mentah pada garis |
| Naik/turun teratur tetapi melengkung | Spearman | cukup urutannya konsisten, nilai boleh melengkung |
| Ada pencilan yang mencurigakan | Spearman | peringkat menahan pengaruh satu nilai ekstrem |
Matriks Korelasi dan Heatmap #
Untuk lebih dari dua kolom, korelasi berpasangan membentuk matriks. Data 12 hari berikut memuat suhu siang, jumlah pengunjung, gelas kopi susu, dan gelas teh tawar yang terjual:
import pandas as pd
cuaca = pd.DataFrame({
"suhu": [26, 31, 24, 29, 33, 27, 25, 30, 28, 32, 26, 34],
"pengunjung": [230, 250, 260, 220, 300, 210, 280, 240, 225, 285, 320, 310],
"kopi_susu": [19, 27, 17, 25, 32, 22, 16, 28, 25, 31, 21, 34],
"teh_tawar": [29, 20, 33, 23, 17, 32, 30, 23, 25, 19, 27, 15],
})
print(cuaca.corr(numeric_only=True).round(2))Output yang Dihasilkan:
suhu pengunjung kopi_susu teh_tawar
suhu 1.00 0.31 0.98 -0.96
pengunjung 0.31 1.00 0.29 -0.43
kopi_susu 0.98 0.29 1.00 -0.94
teh_tawar -0.96 -0.43 -0.94 1.00Matriks ini simetris: nilai di sel (i, j) sama dengan (j, i), dan diagonal selalu 1,00. Tiga temuan menonjol: suhu dengan kopi_susu mencatat 0,98 dan dengan teh_tawar mencatat -0,96 — cuaca menggerakkan dua menu itu berlawanan arah; korelasi kopi_susu dengan teh_tawar (-0,94) hanyalah turunan dari dua hubungan tersebut; dan baris pengunjung nyaris pucat — kunjungan tidak mengikuti suhu, jadi penjualan dingin memang soal menu, bukan sekadar banyak orang. Matriks sebesar ini lebih cepat dibaca sebagai heatmap:
import matplotlib.pyplot as plt
import pandas as pd
cuaca = pd.DataFrame({
"suhu": [26, 31, 24, 29, 33, 27, 25, 30, 28, 32, 26, 34],
"pengunjung": [230, 250, 260, 220, 300, 210, 280, 240, 225, 285, 320, 310],
"kopi_susu": [19, 27, 17, 25, 32, 22, 16, 28, 25, 31, 21, 34],
"teh_tawar": [29, 20, 33, 23, 17, 32, 30, 23, 25, 19, 27, 15],
})
matriks = cuaca.corr(numeric_only=True)
plt.imshow(matriks, cmap="RdBu_r", vmin=-1, vmax=1)
plt.colorbar(label="Korelasi")
plt.xticks(range(len(matriks.columns)), matriks.columns, rotation=20)
plt.yticks(range(len(matriks.columns)), matriks.columns)
for i in range(len(matriks)):
for j in range(len(matriks)):
plt.text(j, i, f"{matriks.iloc[i, j]:.2f}", ha="center", va="center")
plt.title("Heatmap matriks korelasi, 12 hari operasional")
plt.show()Heatmap yang tergambar adalah kisi 4x4 dengan dua arah warna: merah pekat untuk korelasi mendekati +1 dan biru pekat untuk mendekati -1, sementara nilai dekat nol tampil nyaris putih. Diagonalnya tersusun kotak merah gelap bertuliskan 1,00; blok suhu-kopi_susu menyala merah terang, blok suhu-teh_tawar menyala biru, dan baris pengunjung tampak pucat dihiasi angka kecil. Dengan sekali lirik, mata langsung mendaratkan perhatian pada pasangan yang kuat dan mengabaikan yang lemah — itulah fungsi heatmap pada laporan eksplorasi.
Korelasi Semu dan Batas Tafsir #
Sekarang contoh yang mengingatkan kita akan batas. Toko Kopi Kita mencatat total penjualan kopi susu per tahun selama delapan tahun, dan pada periode yang sama harga tiket masuk museum kota naik berkali-kali:
import pandas as pd
tahunan = pd.DataFrame({
"tahun": [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023],
"kopi_susu_ribu": [120, 135, 150, 170, 190, 215, 240, 270],
"tiket_museum": [5.0, 5.5, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0],
})
r = tahunan["kopi_susu_ribu"].corr(tahunan["tiket_museum"])
print("Korelasi penjualan kopi susu vs harga tiket museum:", round(r, 3))Output yang Dihasilkan:
Korelasi penjualan kopi susu vs harga tiket museum: 0.996Korelasinya 0,996 — setinggi hubungan harga-promosi pada chapter sebelumnya. Tetapi tidak ada mekanisme yang masuk akal menghubungkan keduanya: pengunjung museum tidak membeli puluhan ribu gelas kopi susu saat tiketnya naik, dan kafe tidak menaikkan tiket museum. Kedua deret menanjak karena sama-sama menunggangi tren yang lebih besar — pertumbuhan kota dan kenaikan harga umum — sehingga waktu menjadi confounder yang tak terlihat pada tabel. Korelasi seperti ini disebut korelasi semu (spurious correlation): angkanya tinggi, hubungannya kosong.
Sebelum menutup, mari kita tetapkan batas tafsir dengan satu daftar pengecekan. Temuan korelasi tinggi hanya membuktikan bahwa dua variabel bergerak bersama. Penjelasannya bisa salah satu dari empat: X memengaruhi Y, Y memengaruhi X, variabel ketiga memengaruhi keduanya (seperti kota pada chapter multivariat dan waktu pada contoh museum), atau kebetulan belaka. Memilah keempatnya menuntut desain eksperimen atau metode kausal tersendiri — bukan angka korelasi yang lebih tinggi.
Rangkuman #
- Pearson adalah rata-rata hasil kali skor-z kedua variabel;
corr()pandas menghitungnya dari nilai mentah dan paling tepat untuk hubungan garis lurus. - Spearman bekerja pada peringkat, sehingga tetap sempurna untuk hubungan monoton yang melengkung dan lebih tahan terhadap pencilan.
scipy.stats.pearsonrdanspearmanrmelengkapi r dengan p-value — peluang melihat hubungan seerat itu bila data sebenarnya tak berhubungan.- Matriks korelasi dibaca simetris dengan diagonal 1,00; heatmap memetakan kekuatan ke warna sehingga pasangan kuat langsung terlihat.
- Korelasi tinggi bisa lahir dari confounder atau kebetulan — korelasi semu — dan tidak pernah dengan sendirinya membuktikan sebab-akibat.
Korelasi menjawab “seberapa erat dua variabel bergerak bersama”, tetapi pertanyaan bisnis sering menuntut lebih: berapa gelas tambahan yang terjual bila harga turun 1.000 rupiah? Berapa perkiraan penjualan pekan depan? Untuk menjawab “berapa”, kita butuh model yang menempatkan hubungan itu pada satu garis — pekerjaan Regresi Linear .