Analisis bivariat memberi jawaban yang rapi, tetapi dunia nyata jarang sependek itu. Iklan memang berkorelasi dengan penjualan, tetapi toko yang besar iklannya biasanya juga toko di kota besar dengan pengunjung banyak — variabel ketiga yang tidak ikut diperhitungkan mampu membuat hubungan tampak jauh lebih kuat, atau bahkan berlawanan arah, dari kenyataannya. Analisis multivariat adalah pemeriksaan tiga variabel atau lebih secara bersamaan: merangkum berlapis, memvisualisasikan dengan dimensi tambahan, memeriksa keterkaitan antar variabel bebas, dan mengendalikan variabel pengganggu. Pada chapter ini kita jalankan keempatnya pada satu dataset yang sama.
Dataset Penjualan Tiga Kota #
Kita memakai catatan dua pekan dari tiga cabang Toko Kopi Kita — Bandung, Surabaya, dan Medan. Setiap baris adalah gabungan kota, menu, dan pekan, lengkap dengan pengeluaran iklan pekan itu (ribu rupiah), jumlah pengunjung, dan gelas terjual:
kota,menu,pekan,iklan_ribu,pengunjung,penjualan_gelas
Bandung,kopi susu,pekan-1,60,540,380
Bandung,kopi susu,pekan-2,80,560,390
Bandung,kopi hitam,pekan-1,55,470,310
Bandung,kopi hitam,pekan-2,78,500,300
Bandung,matcha latte,pekan-1,62,510,430
Bandung,matcha latte,pekan-2,88,600,450
Bandung,teh tawar,pekan-1,58,450,280
Bandung,teh tawar,pekan-2,75,460,270
Surabaya,kopi susu,pekan-1,38,340,270
Surabaya,kopi susu,pekan-2,55,380,280
Surabaya,kopi hitam,pekan-1,35,300,220
Surabaya,kopi hitam,pekan-2,52,310,210
Surabaya,matcha latte,pekan-1,40,330,310
Surabaya,matcha latte,pekan-2,58,400,320
Surabaya,teh tawar,pekan-1,36,290,190
Surabaya,teh tawar,pekan-2,50,300,185
Medan,kopi susu,pekan-1,15,200,160
Medan,kopi susu,pekan-2,26,220,165
Medan,kopi hitam,pekan-1,13,160,120
Medan,kopi hitam,pekan-2,24,170,115
Medan,matcha latte,pekan-1,16,190,180
Medan,matcha latte,pekan-2,28,210,185
Medan,teh tawar,pekan-1,12,150,100
Medan,teh tawar,pekan-2,22,145,95Meringkas Berlapis dengan pivot_table #
Pertanyaan pertama yang mustahil dijawab bivariat: bagaimana rata-rata penjualan menurut kota sekaligus menurut menu? pivot_table() menjawabnya dengan indeks bertingkat — daftar ["kota", "menu"] pada index menghasilkan baris dua lapis, dan aggfunc="mean" meringkas dua pekan menjadi satu angka per kombinasi:
import pandas as pd
penjualan = pd.read_csv("penjualan_mingguan.csv")
tabel = pd.pivot_table(penjualan, index=["kota", "menu"],
values="penjualan_gelas", aggfunc="mean")
print(tabel.round(1))Output yang Dihasilkan:
penjualan_gelas
kota menu
Bandung kopi hitam 305.0
kopi susu 385.0
matcha latte 440.0
teh tawar 275.0
Medan kopi hitam 117.5
kopi susu 162.5
matcha latte 182.5
teh tawar 97.5
Surabaya kopi hitam 215.0
kopi susu 275.0
matcha latte 315.0
teh tawar 187.5Tabel ini memperlihatkan dua pola yang saling bertumpuk. Pola pertama, urutan menu konsisten di setiap kota: matcha latte selalu tertinggi, disusul kopi susu, kopi hitam, lalu teh tawar. Pola kedua, level antar kota sangat berbeda — penjualan teh tawar di Bandung (275) lebih tinggi daripada kopi susu di Medan (162,5). Dua pola ini berasal dari dua variabel kategorikal yang berbeda, dan hanya tampilan berlapis seperti ini yang menampung keduanya sekaligus.
Scatter Plot Tiga Dimensi dengan Warna #
Scatter plot biasa hanya memuat dua sumbu. Variabel ketiga bisa masuk lewat warna titik — di sini setiap kota mendapat warna sendiri, sehingga satu grafik kini memuat pengunjung, penjualan, dan kota:
import matplotlib.pyplot as plt
import pandas as pd
penjualan = pd.read_csv("penjualan_mingguan.csv")
for kota, grup in penjualan.groupby("kota"):
plt.scatter(grup["pengunjung"], grup["penjualan_gelas"], label=kota)
plt.xlabel("Pengunjung per pekan")
plt.ylabel("Gelas terjual per pekan")
plt.title("Pengunjung vs penjualan di tiga kota")
plt.legend(title="Kota")
plt.show()Grafik yang terbentuk menampilkan tiga gugus titik yang terpisah rapi: gugus Medan di kiri bawah (pengunjung 145-220), gugus Surabaya di tengah, dan gugus Bandung di kanan atas (pengunjung 450-600). Di dalam setiap gugus, titik-titik menanjak searah — makin banyak pengunjung, makin banyak gelas terjual. Pemisahan antar gugus itulah informasi ketiga yang tidak terlihat pada scatter plot dua dimensi: sebagian besar variasi penjualan ternyata mengikuti batas kota, bukan sekadar posisi pada garis.
Matriks Korelasi dan Multikolinearitas #
Sebelum memodelkan penjualan, kita periksa dulu keterkaitan seluruh kolom numerik sekaligus. corr() pada seluruh data frame menghasilkan matriks korelasi berpasangan:
import pandas as pd
penjualan = pd.read_csv("penjualan_mingguan.csv")
print(penjualan.corr(numeric_only=True).round(2))Output yang Dihasilkan:
iklan_ribu pengunjung penjualan_gelas
iklan_ribu 1.00 0.95 0.85
pengunjung 0.95 1.00 0.95
penjualan_gelas 0.85 0.95 1.00Matriks ini dibaca baris demi baris, dan satu selnya menuntut perhatian khusus: korelasi iklan_ribu dengan pengunjung mencapai 0,95 — dua calon variabel penjelas yang saling berkorelasi sangat kuat. Gejala ini bernama multikolinearitas: iklan besar dan pengunjung banyak muncul bersama-sama (keduanya ciri kota besar), sehingga sulit memisahkan sumbangan masing-masing dalam sebuah model. Ketika dua variabel penjelas membawa informasi yang hampir sama, koefisien model menjadi rapuh dan tafsirannya menyesatkan; penanganannya dibahas pada chapter Penanganan Fitur Berkorelasi
.
Mengendalikan Variabel dengan groupby #
Temuan yang paling menentukan lahir dari pertanyaan berikut: apakah iklan benar-benar berhubungan dengan penjualan, ataukah keduanya hanya sama-sama mengikuti besarnya kota? Kita uji dengan memecah korelasi per kota — variabel kota dikendalikan karena setiap korelasi kini dihitung di dalam satu kota saja:
import pandas as pd
penjualan = pd.read_csv("penjualan_mingguan.csv")
r_iklan = penjualan["iklan_ribu"].corr(penjualan["penjualan_gelas"])
r_pengunjung = penjualan["pengunjung"].corr(penjualan["penjualan_gelas"])
print(f"{'Seluruh data':11s} : iklan {r_iklan:.2f} | pengunjung {r_pengunjung:.2f}")
for kota, grup in penjualan.groupby("kota"):
r_iklan = grup["iklan_ribu"].corr(grup["penjualan_gelas"])
r_pengunjung = grup["pengunjung"].corr(grup["penjualan_gelas"])
print(f"{kota:11s} : iklan {r_iklan:.2f} | pengunjung {r_pengunjung:.2f}")Output yang Dihasilkan:
Seluruh data : iklan 0.85 | pengunjung 0.95
Bandung : iklan 0.32 | pengunjung 0.86
Medan : iklan 0.33 | pengunjung 0.91
Surabaya : iklan 0.29 | pengunjung 0.84Kontras pada output itu adalah pelajaran terpenting chapter ini:
- Korelasi iklan runtuh setelah dikendalikan: 0,85 secara keseluruhan, tetapi hanya 0,29 sampai 0,33 di dalam setiap kota. Sebagian besar hubungan “iklan mendorong penjualan” ternyata dibawa oleh perbedaan antar kota — kota besar beriklan besar sekaligus menjual banyak.
- Korelasi pengunjung bertahan: 0,95 secara keseluruhan dan tetap 0,84 sampai 0,91 di dalam setiap kota. Hubungan pengunjung-penjualan bertahan di semua kondisi, jadi jauh lebih layak dianggap hubungan yang sesungguhnya.
- Kota berperan sebagai confounder: variabel ketiga yang memengaruhi dua variabel yang kita amati sekaligus. Teknik
groupbyper kota adalah bentuk paling sederhana dari analisis yang mengendalikan confounder.
Rangkuman #
pivot_table()denganindex=["kota", "menu"]meringkas penjualan dalam indeks bertingkat dan memperlihatkan dua pola kategorikal yang bertumpuk sekaligus.- Warna pada scatter plot menghadirkan dimensi ketiga: gugus per kota memperlihatkan bahwa sebagian besar variasi mengikuti batas kota.
- Matriks
corr()antar variabel numerik memperingatkan multikolinearitas —iklan_ribudanpengunjungberkorelasi 0,95 sehingga keduanya tidak boleh dipakai bersama tanpa pertimbangan. - Mengendalikan confounder dengan
groupbymengubah kesimpulan: korelasi iklan-penjualan 0,85 runtuh menjadi sekitar 0,3 per kota, sementara korelasi pengunjung-penjualan bertahan.
Kita baru saja memakai angka korelasi berpasangan berulang kali, dan dua temuan kita — korelasi yang runtuh dan korelasi yang bertahan — menunjukkan bahwa tidak semua angka korelasi setara. Chapter berikutnya membedah alat itu sendiri: rumus di baliknya, pilihan Pearson atau Spearman, matriksnya, serta batas tafsir yang memisahkan korelasi dari kausalitas — di Analisis Korelasi .