Bagian 5 menunjukkan pergerakan; bagian ini mengukurnya. Pertanyaan Q1 dari Bagian 1 — seberapa bergejolak harga tiap komoditas — akhirnya kita jawab dengan tiga angka baku: rata-rata sebagai titik pusat, median sebagai pembanding yang tahan lonjakan, dan simpangan baku sebagai ukuran sebaran. Lalu, karena kelima komoditas berdagang di tingkat harga yang berbeda, kita menutup dengan satu ukuran yang membuat semuanya sebanding: koefisien variasi. Konsep tendensi sentral dan ukuran penyebaran sudah kita bahas pada Tendensi Sentral dan Ukuran Penyebaran ; di sini keduanya bekerja untuk data warung nyata.

Tiga Angka Per Komoditas #

Satu panggilan agg() merangkum lima statistik sekaligus untuk tiap komoditas:

python
import pandas as pd

# Resep pembersihan Bagian 4: 41 baris mentah menjadi 40 baris bersih.
df = pd.read_csv("../data/harga_komoditas.csv")
df = df.drop_duplicates(subset=["minggu", "komoditas"], keep="first").copy()
df["komoditas"] = df["komoditas"].str.strip().str.lower()
df["harga_rata_ribu"] = pd.to_numeric(df["harga_rata_ribu"], errors="coerce")
df = df.sort_values(["komoditas", "minggu"])
df["harga_rata_ribu"] = df.groupby("komoditas")["harga_rata_ribu"].transform(
    lambda s: s.interpolate()
)

stat = df.groupby("komoditas")["harga_rata_ribu"].agg(["mean", "median", "std", "min", "max"])
print(stat.round(2).to_string())

Output yang Dihasilkan:

text
               mean  median    std   min   max
komoditas                                     
ayam broiler  34.00   33.90   0.78  33.0  35.2
bawang merah  32.94   32.75   2.01  30.0  36.0
beras         13.25   13.25   0.16  13.0  13.5
cabai merah   50.25   43.00  14.53  38.0  78.0
gula pasir    17.65   17.65   0.12  17.5  17.8

Tabel kecil ini menyimpan tiga temuan penting:

  1. Cabai merah: mean 50.25 jauh di atas median 43.00. Selisih sebesar itu terjadi karena dua pekan lonjakan (65.0 dan 78.0) menarik rata-rata ke atas, padahal mayoritas pekan harga cabai berkisar 38–44. Ketika mean dan median berpisah jauh, datanya miring — dan miringnya bersumber dari lonjakan M4–M5.
  2. Beras dan gula pasir: mean nyaris menyatu dengan median, std kecil. Beras 13.25/13.25 dan gula 17.65/17.65 — pola harga yang stabil dan simetris, tanpa kejutan.
  3. min dan max membingkai rentang penuh: cabai 38.0–78.0 (rentang 40.0 ribu!), beras 13.0–13.5 (rentang 0.5), gula 17.5–17.8 (rentang 0.3).

Menghitung Simpangan Baku dari Nol #

Sebelum memakai angka std di atas, mari kita pastikan tidak ada sulap di dalamnya. Rumus simpangan baku sampel:

text
s = akar( jumlah((x - rata_rata)^2) / (n - 1) )

Tiap titik dihitung selisihnya dari rata-rata, dikuadratkan agar arah naik-turun tidak saling menghapus, dijumlahkan, dibagi n - 1 (koreksi sampel), lalu diakarkan agar kembali ke satuan rupiah. Kita hitung manual untuk beras dan bandingkan dengan hasil .std():

python
import math
import pandas as pd

df = pd.read_csv("../data/harga_komoditas.csv")
df = df.drop_duplicates(subset=["minggu", "komoditas"], keep="first").copy()
df["komoditas"] = df["komoditas"].str.strip().str.lower()
df["harga_rata_ribu"] = pd.to_numeric(df["harga_rata_ribu"], errors="coerce")
df = df.sort_values(["komoditas", "minggu"])
df["harga_rata_ribu"] = df.groupby("komoditas")["harga_rata_ribu"].transform(
    lambda s: s.interpolate()
)
beras = df[df["komoditas"] == "beras"]["harga_rata_ribu"]

selisih_kuadrat = [(x - beras.mean()) ** 2 for x in beras]
std_manual = math.sqrt(sum(selisih_kuadrat) / (len(beras) - 1))

print(f"Rata-rata beras           : {beras.mean():.4f}")
print(f"std beras (hitung manual) : {std_manual:.4f}")
print(f"std beras (metode .std()) : {beras.std():.4f}")

Output yang Dihasilkan:

text
Rata-rata beras           : 13.2500
std beras (hitung manual) : 0.1604
std beras (metode .std()) : 0.1604

Kedua hasil identik sampai empat angka desimal, dan itu bukan kebetulan: metode .std() pandas memakai pembagi n - 1 (simpangan baku sampel) — sama dengan rumus manual kita. Kalau suatu saat Anda menemukan std yang “melenceng”, periksa dulu pembagi yang dipakai: n - 1 (sampel, ddof=1) atau n (populasi, ddof=0).

Koefisien Variasi untuk Membandingkan Antar Komoditas #

Sekarang persoalan adilnya perbandingan. Std cabai 14.53 tampak menumpulkan std beras 0.16 — tetapi cabai memang berdagang di kisaran 50 ribu sementara beras di 13 ribu. Komoditas mahal otomatis punya “ruang rupiah” lebih luas untuk berayun. Ukuran yang membandingkan sebaran relatif terhadap tingkat harganya sendiri adalah koefisien variasi:

text
cv = (std / mean) x 100%
python
import pandas as pd

df = pd.read_csv("../data/harga_komoditas.csv")
df = df.drop_duplicates(subset=["minggu", "komoditas"], keep="first").copy()
df["komoditas"] = df["komoditas"].str.strip().str.lower()
df["harga_rata_ribu"] = pd.to_numeric(df["harga_rata_ribu"], errors="coerce")
df = df.sort_values(["komoditas", "minggu"])
df["harga_rata_ribu"] = df.groupby("komoditas")["harga_rata_ribu"].transform(
    lambda s: s.interpolate()
)

stat = df.groupby("komoditas")["harga_rata_ribu"].agg(["mean", "std"])
stat["cv"] = stat["std"] / stat["mean"] * 100
print(stat.sort_values("cv", ascending=False).round(2).to_string())

Output yang Dihasilkan:

text
               mean    std     cv
komoditas                        
cabai merah   50.25  14.53  28.91
bawang merah  32.94   2.01   6.10
ayam broiler  34.00   0.78   2.29
beras         13.25   0.16   1.21
gula pasir    17.65   0.12   0.68

Tabel ini adalah jawaban Q1 dan inti seluruh proyek:

KomoditascvCara baca
cabai merah28.91%Harga berayun hampir sepertiga tingkat rata-ratanya — paling bergejolak
bawang merah6.10%Bergelombang sedang, naik-turun tapi terkendali
ayam broiler2.29%Stabil secara mingguan (trennya kita bahas di Bagian 7)
beras1.21%Nyaris datar
gula pasir0.68%Paling tenang sepanjang periode

Perhatikan bagaimana cv menata ulang dunia: ayam broiler yang std-nya 0.78 — lima kali std beras — ternyata sama-sama tergolong stabil karena ayunannya kecil dibanding tingkat harganya. Rincian penggunaan agg() per kolom ada di dokumentasi pandas tentang groupby .

Ringkasan Bagian 6 #

Statistik lima angka memberi bentuk terukur: cabai merah paling bergejolak (std 14.53, cv 28.91%, mean terpisah 7.25 dari median), bawang merah menengah (cv 6.10%), sementara ayam, beras, dan gula pasir stabil dengan cv di bawah 2.5%. Verifikasi manual memastikan hitungan pandas transparan, dan cv membuat lima komoditas dengan tingkat harga berbeda bisa diperbandingkan secara adil.

Satu hal belum kita lihat: arah pergerakan. Std dan cv mengukur ayunan, tetapi tidak membedakan harga yang pulih (naik lalu turun, seperti cabai) dari harga yang merayap naik terus. Arah itulah yang kita kejar pada Bagian 7: Analisis Tren dan Musiman .