Profil tiap kolom kini kita pegang, tetapi keputusan hampir tidak pernah lahir dari satu kolom saja. Pengelola kafe bertanya apakah harga promosi menekan penjualan, apakah nilai transaksi berbeda antar menu, dan apakah menu tertentu dibayar dengan cara tertentu — semuanya pertanyaan tentang dua variabel sekaligus. Analisis bivariat adalah pemeriksaan hubungan antara tepat dua variabel, dan kuncinya ada pada satu disiplin: alat yang kita pilih harus mengikuti kombinasi tipe keduanya. Pada chapter ini kita kerjakan ketiga kombinasi itu satu per satu dengan prosedur yang baku.

Matriks Kombinasi Tipe Variabel #

Setiap analisis bivariat bermuara pada salah satu dari tiga kombinasi tipe, dan masing-masing punya pertanyaan pokok serta alat utama yang berbeda:

KombinasiPertanyaan pokokAlat utamaCara membaca hasil
Numerik vs numerikapakah dua angka bergerak bersama?scatter plot + korelasiarah, kekuatan, bentuk pola
Kategorikal vs numerikapakah angka berbeda antar kelompok?groupby + rata-rata per kelompokselisih rata-rata, sebaran tiap kelompok
Kategorikal vs kategorikalapakah dua kategori seiring sejalan?crosstab + proporsiperbandingan proporsi antar baris

Kita sudah mencicipi ketiganya secara lepas pada chapter Hubungan antar Variabel ; tugas kita sekarang menjalankannya sebagai prosedur utuh — dari memilih alat, membaca hasil, sampai melaporkannya dengan disiplin. Urutan pengerjaan mengikuti tabel di atas: mulai dari pasangan numerik yang paling ringkas, lalu naik ke pasangan yang melibatkan kategori.

Numerik vs Numerik: Seberapa Erat Dua Angka Bergerak Bersama #

Kasus pertama datang dari empat belas hari program promosi kopi susu di Toko Kopi Kita. Setiap hari kasir menurunkan harga jual pada rentang berbeda, lalu mencatat berapa gelas terjual — dua kolom numerik pada hari yang sama:

python
import pandas as pd

promo = pd.DataFrame({
    "harga_promo": [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 22, 24, 26],
    "gelas_terjual": [42, 40, 37, 35, 33, 30, 28, 26, 23, 21, 19, 31, 27, 24],
})

r = promo["harga_promo"].corr(promo["gelas_terjual"])
print("Korelasi harga promosi vs gelas terjual:", round(r, 3))

Output yang Dihasilkan:

text
Korelasi harga promosi vs gelas terjual: -0.996

Satu baris kode memberi dua informasi sekaligus. Tanda negatif membetulkan intuisi: hari dengan harga lebih tinggi adalah hari dengan penjualan lebih rendah. Magnitudonya, 0,996, berada di wilayah hubungan yang sangat kuat — harga dan penjualan bergerak hampir selalu berlawanan arah dengan rapat. Sebelum melaporkan angka sebesar itu, kita wajib melihat wujudnya:

python
import matplotlib.pyplot as plt

harga_promo = [18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 22, 24, 26]
gelas_terjual = [42, 40, 37, 35, 33, 30, 28, 26, 23, 21, 19, 31, 27, 24]

plt.scatter(harga_promo, gelas_terjual)
plt.xlabel("Harga promosi kopi susu (ribu rupiah)")
plt.ylabel("Gelas terjual per hari")
plt.title("Harga promosi vs penjualan harian, Toko Kopi Kita")
plt.show()

Empat belas titik pada grafik menyusun pita yang menurun rapat dari kiri atas ke kanan bawah — tidak ada satu titik pun yang melompat jauh dari barisan. Inilah bentuk visual dari korelasi -0,996. Jika seandainya ada satu titik yang berdiri sendiri jauh dari pita, angka korelasi perlu diperiksa ulang karena satu pencilan saja sanggup menggelembungkan nilai r; bab alat ukurnya kita bedah tuntas pada chapter Analisis Korelasi .

Kategorikal vs Numerik: Membandingkan Angka antar Kelompok #

Kasus kedua memakai 30 transaksi yang mencatat tiga hal: menu yang dibeli, metode pembayaran, dan nilai transaksi (ribu rupiah). Nilai transaksi adalah numerik; menu adalah kategorikal — kombinasi yang dibaca lewat ringkasan per kelompok:

csv
menu,metode,nilai_ribu
kopi susu,qris,22
kopi susu,tunai,25
kopi susu,qris,21
kopi susu,kartu,28
kopi susu,qris,24
kopi susu,tunai,22
kopi susu,qris,26
kopi susu,kartu,23
kopi susu,qris,21
kopi susu,tunai,27
kopi susu,qris,24
kopi susu,qris,25
kopi hitam,tunai,16
kopi hitam,qris,19
kopi hitam,tunai,17
kopi hitam,kartu,21
kopi hitam,tunai,18
kopi hitam,qris,16
kopi hitam,tunai,20
kopi hitam,kartu,17
kopi hitam,tunai,19
kopi hitam,qris,18
matcha latte,qris,32
matcha latte,kartu,36
matcha latte,qris,30
matcha latte,qris,38
matcha latte,kartu,33
matcha latte,qris,35
matcha latte,qris,31
matcha latte,qris,34

Kita ringkas nilai transaksi per menu dengan tiga ukuran sekaligus — jumlah, rata-rata, dan simpangan baku:

python
import pandas as pd

penjualan = pd.read_csv("penjualan.csv")

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

Output yang Dihasilkan:

text
              count   mean   std
menu                            
kopi hitam       10  18.10  1.66
kopi susu        12  24.00  2.30
matcha latte      8  33.62  2.67

Cara membacanya menuntut dua perbandingan sekaligus:

  1. Antar kelompok: rata-rata naik teratur dari kopi hitam 18,10 ke kopi susu 24,00 ke matcha latte 33,62 — selisih antar menu jauh melampaui sebaran di dalam menu. Pola seperti ini menunjukkan kolom menu membawa informasi nyata tentang nilai_ribu.
  2. Di dalam kelompok: std tiap menu hanya sekitar 1,7 sampai 2,7, jauh lebih kecil daripada jarak antar rata-rata. Artinya menu hampir sepenuhnya menentukan lapisan harga, dan variasi sisanya berasal dari ukuran pesanan.
  3. count sebagai dasar hitung: rata-rata matcha latte dihitung dari delapan transaksi saja. Selisih sebesar itu tetap meyakinkan pada ukuran sampel kecil, tetapi kebiasaan melaporkan count menyelamatkan kita saat kelompoknya timpang.

Kategorikal vs Kategorikal: Proporsi antar Kategori #

Kombinasi terakhir memasangkan dua kolom kategorikal: apakah cara membayar mengikuti menu yang dibeli? Tabulasi silang pd.crosstab() menghitung frekuensi setiap pasangan, lalu normalize="index" mengubahnya menjadi proporsi per baris agar antar menu bisa dibandingkan langsung:

python
import pandas as pd

penjualan = pd.read_csv("penjualan.csv")

jumlah = pd.crosstab(penjualan["menu"], penjualan["metode"])
proporsi = pd.crosstab(penjualan["menu"], penjualan["metode"], normalize="index").round(2)

print(jumlah)
print()
print(proporsi)

Output yang Dihasilkan:

text
metode        kartu  qris  tunai
menu                            
kopi hitam        2     3      5
kopi susu         2     7      3
matcha latte      2     6      0

metode        kartu  qris  tunai
menu                            
kopi hitam     0.20  0.30   0.50
kopi susu      0.17  0.58   0.25
matcha latte   0.25  0.75   0.00

Tabel frekuensi dan tabel proporsi dibaca berpasangan. Dari tabel frekuensi, QRIS memimpin secara keseluruhan dengan 16 dari 30 transaksi. Tabel proporsi per baris mempertajam cerita: pembeli matcha latte membayar QRIS pada 75% transaksi dan tidak sekali pun membayar tunai, sedangkan kopi hitam justru satu-satunya menu yang didominasi uang tunai — separuh transaksinya. Jika proporsi setiap baris mirip dengan proporsi keseluruhan, kedua kolom layak diduga saling bebas; pola yang bergelombang seperti di atas adalah petunjuk bahwa kedua kategori memang berjalan seiring, dengan kata kunci “petunjuk” — mengujinya secara formal dengan uji chi-square adalah materi chapter Analisis Data Kategorikal .

Rangkuman #

  • Analisis bivariat memilih alat berdasarkan kombinasi tipe: scatter plot dan korelasi untuk numerik-numerik, groupby dengan count/mean/std untuk kategorikal-numerik, dan crosstab dengan proporsi untuk kategorikal-kategorikal.
  • Korelasi -0,996 pada kasus harga promosi hanya layak dilaporkan setelah scatter plot memastikan polanya memang berbentuk pita yang rapat.
  • Perbandingan antar kelompok selalu dibaca dua arah: selisih rata-rata antar kelompok dan sebaran di dalam kelompok, dengan count sebagai dasar hitung.
  • crosstab(normalize="index") mengubah frekuensi menjadi proporsi per baris; arah normalisasi harus mengikuti pertanyaan analisis.

Dua variabel sesungguhnya baru cerita sebagian. Harga memengaruhi penjualan, tetapi pengaruhnya mungkin berbeda di tiap kota; menu menentukan nilai transaksi, tetapi mungkin juga berbeda antar jam sibuk. Ketika variabel ketiga masuk untuk memperjelas — atau justru mengubah — hubungan dua variabel, kita berpindah ke Analisis Multivariat .

Referensi #

  1. pandas — API: DataFrame.groupby
  2. pandas — User Guide: Reshaping and Pivot Tables
  3. Matplotlib — Plot Types