Satu kolom numerik kini kita baca dari segala arah, tetapi data yang sesungguhnya jarang berdiri satu per satu kolom. Suhu udara berjalan beriringan dengan penjualan minuman dingin; menu yang dipilih memengaruhi nilai transaksi; dua variabel yang bergerak bersama membawa informasi yang tidak dimiliki salah satunya sendirian. Pada chapter ini kita mengukur hubungan itu dengan angka — korelasi — lalu belajar memilih ukuran yang tepat, membaca arah dan kekuatannya, serta menahan diri dari kesimpulan yang belum diperolehkannya.

Korelasi: Satu Angka untuk Arah dan Kekuatan #

Korelasi mengubah pertanyaan “apakah dua kolom bergerak bersama?” menjadi satu angka antara -1 dan +1. Tandaannya memberi arah: positif berarti keduanya cenderung naik bersama, negatif berarti yang satu naik ketika yang lain turun. Jarak angkanya dari nol memberi kekuatan: makin dekat ke +1 atau -1, makin rapat pasangan nilai bergerak dalam satu pola.

Kita pakai catatan 14 hari dari cabang Surabaya: suhu udara siang hari, gelas kopi susu (disajikan dingin) yang terjual, dan gelas teh tawar (disajikan hangat) yang terjual:

python
import pandas as pd

cuaca = pd.DataFrame({
    "suhu": [26, 31, 24, 29, 33, 27, 25, 30, 28, 32, 26, 34, 29, 31],
    "kopi_susu": [18, 26, 16, 24, 31, 21, 15, 27, 24, 30, 20, 33, 25, 29],
    "teh_tawar": [30, 21, 34, 24, 18, 33, 31, 24, 26, 20, 28, 16, 25, 22],
})

print(cuaca.corr().round(2))

Output yang Dihasilkan:

text
           suhu  kopi_susu  teh_tawar
suhu       1.00       0.98      -0.96
kopi_susu  0.98       1.00      -0.94
teh_tawar -0.96      -0.94       1.00

Cara membaca matriks tersebut:

  1. corr() menghitung korelasi berpasangan untuk seluruh kolom numerik sekaligus; diagonal bernilai 1,00 karena setiap kolom berkorelasi sempurna dengan dirinya sendiri.
  2. suhu vs kopi_susu = 0,98: arah positif, kekuatan sangat kuat — hari panas menjual kopi susu jauh lebih banyak.
  3. suhu vs teh_tawar = -0,96: arah negatif yang hampir sama kuat — saat suhu naik, teh hangat sepi. Dua menu itu bergerak berlawanan arah mengikuti faktor yang sama.
  4. kopi_susu vs teh_tawar = -0,94: turunan dari dua hubungan sebelumnya — keduanya digerakkan suhu dari arah yang berlawanan, sehingga saling bernilai negatif.

Angka korelasi bukan persentase dan tidak punya satuan. Untuk memakainya, kita butuh konvensi membaca kekuatan. Patokan berikut lazim dipakai sebagai bahasa bersama, bukan hukum mutlak:

Nilai absolut rKekuatan hubunganCara membaca
0,00 - 0,20sangat lemahnyaris tak berbeda dari ketiadaan hubungan
0,20 - 0,40lemahada arah, tetapi sebaran nilai masih lebar
0,40 - 0,60sedangpola terlihat jelas, pengecualian masih banyak
0,60 - 0,80kuatmayoritas nilai mengikuti pola
0,80 - 1,00sangat kuatnilai-nilai nyaris berbaris mengikuti pola

Melihat Hubungan dengan Scatter Plot #

Angka korelasi merangkum; grafik memperlihatkan. Scatter plot menempatkan tiap hari sebagai satu titik — suhu di sumbu mendatar, gelas kopi susu di sumbu tegak:

python
import matplotlib.pyplot as plt

suhu = [26, 31, 24, 29, 33, 27, 25, 30, 28, 32, 26, 34, 29, 31]
kopi_susu = [18, 26, 16, 24, 31, 21, 15, 27, 24, 30, 20, 33, 25, 29]

plt.scatter(suhu, kopi_susu)
plt.xlabel("Suhu udara siang hari (derajat Celsius)")
plt.ylabel("Gelas kopi susu terjual")
plt.title("Suhu udara vs penjualan kopi susu, cabang Surabaya")
plt.show()

Grafik yang terbentuk menampilkan empat belas titik yang menyusun pita naik dari kiri bawah ke kanan atas — saat suhu bertambah, gelas terjual ikut bertambah, dan hampir tidak ada titik yang melompat jauh dari barisan. Bentuk inilah wujud visual korelasi +0,98: pita yang rapat dan menanjak. Bayangkan pita yang sama tetapi menurun untuk teh tawar, dan bentuk awan yang tak berpola untuk pasangan berkorelasi dekat nol.

Pearson untuk Garis Lurus, Spearman untuk Tren Teratur #

corr() memakai korelasi Pearson secara bawaan, dan Pearson punya satu syarat penting: hubungan yang diukurnya adalah hubungan garis lurus. Ketika hubungan nyata tetapi melengkung, Pearson menilai rendah. Sebagai contoh, program loyalitas Toko Kopi Kita memberi poin bulanan yang makin besar seiring tingkat keanggotaan naik, sehingga total poin terkumpul bertambah makin cepat — naik teratur, tetapi bukan mengikuti garis lurus:

python
import pandas as pd

keanggotaan = pd.DataFrame({
    "lama_bulan": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "total_poin": [2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90],
})

pearson = keanggotaan["lama_bulan"].corr(keanggotaan["total_poin"])
spearman = keanggotaan["lama_bulan"].corr(keanggotaan["total_poin"], method="spearman")

print("Pearson  :", round(pearson, 3))
print("Spearman :", round(spearman, 3))

Output yang Dihasilkan:

text
Pearson  : 0.982
Spearman : 1.0

Bedah kode dan hasilnya:

  1. Series.corr(lainnya) menghitung korelasi dua kolom tunggal; argumen method="spearman" mengganti rumus dari Pearson ke Spearman.
  2. Spearman = 1,0: Spearman tidak memakai nilai mentah, melainkan peringkat — ia menanyakan “apakah pasangan ini selalu naik bersama?” Dua belas bulan itu naik teratur setiap bulan, jadi hubungan peringkatnya sempurna.
  3. Pearson = 0,982 < 1: Pearson memakai nilai mentah dan “menghukum” lengkungan — pertambahan poin yang makin curam membuat pasangan nilai menjauh dari garis lurus terbaik. Hubungannya nyaris sempurna, tetapi Pearson hanya sanggup melaporkan 0,982.

Pilihan praktisnya sederhana. Gunakan Pearson saat hubungan diperkirakan lurus dan datanya bersih dari nilai ekstrem; gunakan Spearman saat hubungan cukup monoton (selalu naik atau selalu turun) tetapi bentuknya melengkung, atau saat nilai ekstrem mencurigakan — peringkat menahan pengaruh satu nilai yang menjulang.

Hubungan Kategorikal dan Numerik lewat Rata-rata Kelompok #

Bagaimana bila salah satu kolomnya bukan angka? Menu adalah kategori; nilai transaksi adalah angka. Hubungan keduanya dibaca lewat rata-rata per kelompok — ukuran yang telah kita latih pada chapter Analisis Data Numerik, kini dipakai justru untuk membandingkan kelompok:

python
import pandas as pd

pesanan = pd.DataFrame({
    "menu": ["kopi susu"] * 6 + ["teh tawar"] * 6 + ["matcha latte"] * 6,
    "nilai_ribu": [24, 48, 24, 72, 24, 48,
                   20, 40, 20, 20, 60, 20,
                   28, 56, 28, 84, 28, 56],
})

print(pesanan.groupby("menu")["nilai_ribu"].agg(["count", "mean", "std"]).round(2))

Output yang Dihasilkan:

text
              count   mean    std
menu                             
kopi susu         6  40.00  19.60
matcha latte      6  46.67  22.86
teh tawar         6  30.00  16.73

Cara membacanya:

  1. mean per menu (40,00 / 46,67 / 30,00): rata-rata nilai transaksi mengikuti harga satuan menu — teh tawar termurah di posisi bawah, matcha latte termahal di posisi puncak. Selisih rata-rata antar menu adalah bukti bahwa kategori menu membawa informasi tentang angka nilai_ribu.
  2. std per menu (19,60 / 22,86 / 16,73): sebaran di dalam tiap menu tetap lebar karena nilai transaksi juga ditentukan jumlah gelas per pesanan — satu kolom kategorikal jarang menjelaskan segalanya.
  3. count 6 per menu: kelompok yang seimbang membuat perbandingan rata-rata langsung adil; pada kelompok yang timpang, kita perlu lebih hati-hati seperti pelajaran chapter Analisis Frekuensi.

Untuk dua kolom kategorikal sekaligus — misalnya menu berbanding cabang — alatnya adalah tabulasi silang pd.crosstab() yang sudah kita kuasai pada chapter Analisis Frekuensi dan Analisis Data Kategorikal ; hitungan dan proporsinya dibaca persis seperti di sana.

Korelasi Bukan Kausalitas #

Angka 0,98 pada suhu dan kopi susu memang kuat, tetapi perhatikan apa yang boleh disimpulkan darinya. Hal yang sah: suhu dan penjualan bergerak sangat rapat, jadi suhu bisa jadi prediktor yang baik — hari yang panas adalah hari yang tepat menyiapkan stok lebih banyak. Hal yang belum tentu sah: suhu menyebabkan orang membeli kopi susu.

Bedanya penting karena ada dua jenis jebakan. Pertama, penyebab ketiga (confounder): cuaca panas menaikkan penjualan kopi susu sekaligus penjualan es krim di toko sebelah — kopi susu dan es krim akan berkorelasi tinggi tanpa saling menyebabkan. Kedua, kebetulan: dua deret yang sama-sama menanjak (misalnya penjualan dan jumlah penduduk kota) akan berkorelasi meskipun tidak berhubungan sama sekali. Membuktikan sebab-akibat menuntut eksperimen atau metode khusus — bukan sekadar angka korelasi.

Rangkuman #

  • corr() merangkum hubungan dua kolom numerik menjadi satu angka -1 sampai +1: tanda memberi arah, jarak dari nol memberi kekuatan; tabel kekuatan adalah bahasa bersama, bukan hukum mutlak.
  • Pearson (bawaan corr()) mengukur hubungan garis lurus; method="spearman" mengukur kesesuaian peringkat — pilihan yang tepat saat hubungan melengkung atau ada nilai ekstrem.
  • Hubungan kategorikal-numerikal dibaca lewat rata-rata per kelompok (groupby + agg), selalu lengkapi dengan count dan std; dua kolom kategorikal memakai pd.crosstab().
  • Korelasi tinggi hanya membenarkan prediksi, bukan sebab-akibat; penyebab ketiga dan kebetulan adalah dua jebakan yang paling sering memperdaya.

Kita telah membandingkan kolom berdampingan pada satu potret waktu. Padahal banyak hubungan hanya terlihat ketika data dilihat sebagai deret waktu — penjualan naik menjelang akhir pekan, musim hujan menekannya, dan promo mengangkatnya sesaat. Chapter berikutnya melengkapi lensa terakhir ini: Analisis Data Waktu .

Referensi #

  1. pandas — User Guide
  2. pandas — Getting Started: Intro Tutorials
  3. Matplotlib — Plot Types