Analisis Penjualan Toko Online 2025

Dari 13.412 baris data transaksi yang berantakan menjadi dashboard yang bisa dipakai tim manajemen untuk memutuskan stok dan promosi.

Excel SQL (MySQL) Python (pandas) Power BI
Pertanyaan bisnis: (1) Kategori dan kota mana yang paling menyumbang pendapatan? (2) Kapan penjualan mencapai puncak? (3) Berapa banyak data transaksi yang tidak valid dan kenapa?
Langkah 1

Data mentah

Data saya ekspor dari sistem kasir dalam bentuk CSV. Sebelum mengubah apa pun, saya buka di Excel dan baca sekilas untuk mencari kejanggalan. Berikut cuplikan 8 baris pertama (total 13.412 baris, 8 kolom). Sel merah adalah masalah yang saya temukan.

order_idtgl_orderpelanggankotakategoriqtyhargastatus
100105/01/2025Budi SantosoJakartaElektronik2Rp 350.000Selesai
10022025-01-07siti aminahjktFashion1150000selesai
10022025-01-07siti aminahjktFashion1150000selesai
100312 Jan 2025AndiBandungelektronik-1350000Batal
100415/01/2025Dewi LestariSurabayaRumah Tangga3(kosong)Selesai
100520/01/2025RinaBandungFashion2Rp 120.000Selesai
10063/2/25AgusMedanMakanan545000Selesai
100703/02/2025Budi SantosoJakartaElektronik1350000selesai

Masalah yang ditemukan: format tanggal campur aduk, harga bertipe teks ("Rp 350.000"), penulisan kota dan kategori tidak seragam (jkt, Jakarta, elektronik), order_id ganda, qty negatif, dan harga kosong.

Langkah 2

Membersihkan data (data cleaning)

Saya kerjakan dengan Python (pandas) karena datanya sudah belasan ribu baris dan aturannya perlu bisa diulang. Setiap keputusan saya catat supaya bisa dipertanggungjawabkan.

import pandas as pd

df = pd.read_csv("penjualan_mentah.csv")

# 1. Hapus duplikat berdasarkan order_id
df = df.drop_duplicates(subset="order_id")

# 2. Samakan format tanggal
df["tgl_order"] = pd.to_datetime(df["tgl_order"], dayfirst=True, errors="coerce")

# 3. Harga: buang "Rp" dan titik, ubah ke angka
df["harga"] = (df["harga"].astype(str)
               .str.replace(r"[^0-9]", "", regex=True)
               .replace("", None).astype(float))

# 4. Standarisasi teks
df["kota"] = df["kota"].str.strip().str.title().replace({"Jkt": "Jakarta"})
df["kategori"] = df["kategori"].str.strip().str.title()
df["status"] = df["status"].str.strip().str.capitalize()

# 5. Harga kosong diisi median per kategori
df["harga"] = df["harga"].fillna(df.groupby("kategori")["harga"].transform("median"))

# 6. Buang pesanan batal dan qty tidak valid
df = df[(df["status"] == "Selesai") & (df["qty"] > 0)]

Hasilnya, sel yang tadinya merah kini seragam (hijau). Baris duplikat dan pesanan batal (dicoret) dibuang, dan kolom total saya tambahkan.

order_idtgl_orderpelanggankotakategoriqtyhargatotal
10012025-01-05Budi SantosoJakartaElektronik2350000700000
10022025-01-07Siti AminahJakartaFashion1150000150000
10032025-01-12AndiBandungElektronik-1350000dibuang (batal)
10042025-01-15Dewi LestariSurabayaRumah Tangga385000255000
10052025-01-20RinaBandungFashion2120000240000
10062025-02-03AgusMedanMakanan545000225000

Ringkasan pembersihan

  • Baris awal: 13.412
  • Duplikat dibuang: 418
  • Pesanan batal dibuang: 371
  • Qty/harga tidak valid: 143
  • Baris bersih: 12.480

Kenapa harga kosong diisi median?

Rata-rata mudah tergeser harga barang mahal, sedangkan median lebih stabil. Hanya 0,6% baris yang diisi, jadi dampaknya ke total kecil. Asumsi ini saya catat di dokumentasi.

Langkah 3

Mengolah data (analysis)

Data bersih saya muat ke MySQL lalu saya hitung metrik yang menjawab pertanyaan bisnis. Contoh query untuk pendapatan bulanan dan kategori:

-- Pendapatan per bulan
SELECT DATE_FORMAT(tgl_order, '%Y-%m') AS bulan,
       COUNT(*)            AS jumlah_order,
       SUM(qty * harga)    AS pendapatan
FROM penjualan_bersih
GROUP BY bulan
ORDER BY bulan;

-- Kontribusi tiap kategori
SELECT kategori,
       SUM(qty * harga) AS pendapatan,
       ROUND(100 * SUM(qty * harga) /
         (SELECT SUM(qty * harga) FROM penjualan_bersih), 1) AS persen
FROM penjualan_bersih
GROUP BY kategori
ORDER BY pendapatan DESC;

Metrik yang dihitung

  • Total pendapatan = qty × harga
  • Average order value (AOV) = pendapatan ÷ jumlah order
  • Pertumbuhan Q4 vs Q3
  • Kontribusi kategori dan kota (%)

Pembagian tools

  • Excel: pemeriksaan awal dan validasi sampel
  • Python: cleaning dan otomatisasi
  • SQL: agregasi dan penggabungan
  • Power BI: visualisasi dan dashboard
Langkah 4

Dashboard

Hasil query saya hubungkan ke Power BI. Versi di bawah adalah tampilan ringkasnya.

Rp 1,56 MTotal pendapatan
12.480Jumlah order
Rp 125 rbRata-rata nilai order
+32%Q4 dibanding Q3

Pendapatan per bulan (juta rupiah)

Kontribusi kategori

Kontribusi kota

Langkah 5

Temuan dan rekomendasi

Temuan

  • Elektronik menyumbang 38% pendapatan, paling besar.
  • Jakarta dan Bandung bersama menghasilkan 52% penjualan.
  • Penjualan naik tajam di November–Desember (Harbolnas 11.11 dan 12.12, serta gajian).
  • Sekitar 7% data mentah tidak valid, terutama duplikat dan pesanan batal.

Rekomendasi

  • Tambah stok elektronik dan Fashion mulai Oktober.
  • Uji promo ongkir di Medan dan Surabaya yang kontribusinya masih rendah.
  • Tambahkan validasi input di sistem kasir agar format tanggal dan kota seragam.