Data bersih ibarat bahan mentah yang sudah tersortir — sebelum memasak, kita perlu mencium, menimbang, dan mencicipinya. Pada bagian ini kita menjelajahi 48 baris data bersih Toko Kopi Kita tanpa target jawaban spesifik dahulu: melihat sebaran angkanya, menjumlahkan per menu dan per hari, lalu membandingkan akhir pekan dengan hari kerja. Pola yang muncul dari eksplorasi inilah yang nanti dijawab tuntas pada Bagian 7. Pendekatannya mengikuti kerangka Exploratory Data Analysis yang sudah kita pelajari.
Statistik Deskriptif Sekilas #
Titik awal eksplorasi adalah describe() pada kolom-kolom angka. Ingat: setiap blok kode pada proyek ini berdiri sendiri, jadi fungsi pembersihan dari Bagian 5 ikut dituliskan lengkap:
import pandas as pd
def muat_bersih(path):
"""Muat data mentah dan terapkan pembersihan hasil Bagian 5."""
df = pd.read_csv(path).drop_duplicates().reset_index(drop=True)
df["menu"] = df["menu"].str.lower()
df["gelas"] = pd.to_numeric(df["gelas"].replace("-", pd.NA))
valid = df[df["gelas"].notna() & (df["pendapatan_ribu"] > 0)]
harga = (valid["pendapatan_ribu"] / valid["gelas"]).groupby(valid["menu"]).median()
nol = df["pendapatan_ribu"] == 0
df.loc[nol, "pendapatan_ribu"] = (
df.loc[nol, "gelas"] * df.loc[nol, "menu"].map(harga)
).astype(int)
kosong = df["gelas"].isna()
df.loc[kosong, "gelas"] = (
df.loc[kosong, "pendapatan_ribu"] / df.loc[kosong, "menu"].map(harga)
)
df["gelas"] = df["gelas"].astype(int)
return df
bersih = muat_bersih("../data/penjualan_kotor.csv")
print(bersih[["gelas", "pendapatan_ribu"]].describe().round(2).to_string())Output yang Dihasilkan:
gelas pendapatan_ribu
count 48.00 48.00
mean 24.67 492.69
std 10.80 295.56
min 7.00 70.00
25% 17.75 235.00
50% 22.00 444.50
75% 31.50 706.50
max 55.00 1210.00Mari kita baca statistik tersebut:
count48 pada kedua kolom: seluruh baris terisi — pembersihan Bagian 5 benar-benar menyisakan data yang utuh.meangelas 24,67 dan pendapatan 492,69 (ribu): itulah penjualan rata-rata satu menu pada satu hari. Kalikan 4 menu dan 12 hari, hasilnya konsisten dengan total 48 baris.mingelas 7 danmax55: jarak minimum-maksimum yang lebar menandakan penjualan per menu-hari sangat bervariasi — dari hari sepi (14 Januari) sampai puncak akhir pekan. Nilai maksimum 55 gelas itu milik kopi susu pada 11 Januari.stdyang besar (10,8 gelas; 295,56 ribu): sebaran yang lebar ini wajar untuk usaha kuliner dan menjadi alasan kuat mengapa kita harus melihat agregasi per kelompok, bukan hanya rata-rata keseluruhan.
Total per Menu dan per Hari #
Dua agregasi paling mendasar: jumlahkan per menu untuk melihat performa produk, dan jumlahkan per tanggal untuk membaca ritme harian:
import pandas as pd
def muat_bersih(path):
"""Muat data mentah dan terapkan pembersihan hasil Bagian 5."""
df = pd.read_csv(path).drop_duplicates().reset_index(drop=True)
df["menu"] = df["menu"].str.lower()
df["gelas"] = pd.to_numeric(df["gelas"].replace("-", pd.NA))
valid = df[df["gelas"].notna() & (df["pendapatan_ribu"] > 0)]
harga = (valid["pendapatan_ribu"] / valid["gelas"]).groupby(valid["menu"]).median()
nol = df["pendapatan_ribu"] == 0
df.loc[nol, "pendapatan_ribu"] = (
df.loc[nol, "gelas"] * df.loc[nol, "menu"].map(harga)
).astype(int)
kosong = df["gelas"].isna()
df.loc[kosong, "gelas"] = (
df.loc[kosong, "pendapatan_ribu"] / df.loc[kosong, "menu"].map(harga)
)
df["gelas"] = df["gelas"].astype(int)
return df
bersih = muat_bersih("../data/penjualan_kotor.csv")
per_menu = (
bersih.groupby("menu")[["gelas", "pendapatan_ribu"]]
.sum()
.sort_values("pendapatan_ribu", ascending=False)
)
print("Total per menu (12 hari):")
print(per_menu.to_string())
per_hari = bersih.groupby("tanggal")["pendapatan_ribu"].sum().reset_index()
per_hari.columns = ["tanggal", "total_ribu"]
print("\nTotal pendapatan per hari (ribu rupiah):")
print(per_hari.to_string(index=False))Output yang Dihasilkan:
Total per menu (12 hari):
gelas pendapatan_ribu
menu
kopi susu 459 10098
matcha latte 291 7275
americano 242 4356
teh tawar 192 1920
Total pendapatan per hari (ribu rupiah):
tanggal total_ribu
2026-01-05 1747
2026-01-06 1565
2026-01-07 1824
2026-01-08 1662
2026-01-09 1956
2026-01-10 2743
2026-01-11 2915
2026-01-12 2053
2026-01-13 1881
2026-01-14 903
2026-01-15 2128
2026-01-16 2272import pandas as pd
def muat_bersih(path):
"""Muat data mentah dan terapkan pembersihan hasil Bagian 5."""
df = pd.read_csv(path).drop_duplicates().reset_index(drop=True)
df["menu"] = df["menu"].str.lower()
df["gelas"] = pd.to_numeric(df["gelas"].replace("-", pd.NA))
valid = df[df["gelas"].notna() & (df["pendapatan_ribu"] > 0)]
harga = (valid["pendapatan_ribu"] / valid["gelas"]).groupby(valid["menu"]).median()
nol = df["pendapatan_ribu"] == 0
df.loc[nol, "pendapatan_ribu"] = (
df.loc[nol, "gelas"] * df.loc[nol, "menu"].map(harga)
).astype(int)
kosong = df["gelas"].isna()
df.loc[kosong, "gelas"] = (
df.loc[kosong, "pendapatan_ribu"] / df.loc[kosong, "menu"].map(harga)
)
df["gelas"] = df["gelas"].astype(int)
return df
bersih = muat_bersih("../data/penjualan_kotor.csv")
AKHIR_PEKAN = ("2026-01-10", "2026-01-11") # Sabtu dan Minggu
per_hari = bersih.groupby("tanggal")["pendapatan_ribu"].sum().reset_index()
per_hari["akhir_pekan"] = per_hari["tanggal"].isin(AKHIR_PEKAN)
ringkas = per_hari.groupby("akhir_pekan")["pendapatan_ribu"].agg(["count", "mean"])
print("Rata-rata pendapatan harian (ribu rupiah):")
print(ringkas.round(1).to_string())
rasio = ringkas.loc[True, "mean"] / ringkas.loc[False, "mean"]
print(f"\nRasio akhir pekan terhadap hari kerja: {rasio:.2f}")Output yang Dihasilkan:
Rata-rata pendapatan harian (ribu rupiah):
count mean
akhir_pekan
False 10 1799.1
True 2 2829.0
Rasio akhir pekan terhadap hari kerja: 1.57Pembacaannya:
count2 vs 10: kelompok akhir pekan hanya berisi dua hari, jadi angka rata-ratanya lebih mudah goyah dibanding kelompok hari kerja yang berisi sepuluh hari. Keterbatasan ini kita catat untuk laporan.- Rata-rata 2.829,0 vs 1.799,1: akhir pekan unggul hampir 1.030 ribu rupiah per hari.
- Rasio 1,57: pendapatan akhir pekan rata-rata 1,57 kali hari kerja — selisih yang terlalu besar untuk dianggap kebetulan, meski tetap perlu dipantau beberapa pekan lagi sebelum menjadi kebijakan tetap.
Eksplorasi telah memetakan medannya: satu menu penopang, akhir pekan yang ramai, dan satu hari yang menyimpang. Kini lima pertanyaan dari Bagian 2 tinggal dijawab satu per satu dengan angka — itu tugas Bagian 7: Analisis Penjualan .