Pertemuan 02 - Pandas Fundamental

Pertemuan 02 - Pandas Fundamental

Mendalami DataFrame, pembacaan CSV, penyaringan, dan pengurutan data penjualan secara menyeluruh menggunakan Pandas.

Tujuan Praktikum

Setelah menyelesaikan praktikum ini, mahasiswa mampu:

  1. Menjelaskan anatomi DataFrame dan Series, serta membuat DataFrame dari berbagai sumber.
  2. Memilih data secara presisi menggunakan .loc (berbasis label) dan .iloc (berbasis posisi).
  3. Membaca CSV dengan parameter penting, termasuk mengubah kolom tanggal menjadi tipe datetime.
  4. Menyaring data dengan kondisi majemuk (&, |, ~), between(), isin(), metode str, dan query().
  5. Mengurutkan data secara multi-level serta mengambil nilai ekstrem dengan nlargest/nsmallest.
  6. Membangun tabel ringkasan dengan agg() untuk menemukan produk terlaris, termurah, dan termahal.

Persiapan

Kebutuhan praktikum:

text
- Akun Google
- Google Colab
- Koneksi internet
- Dataset penjualan.csv (studi kasus Toko Elektronik)

Buat notebook baru bernama Pertemuan02_NamaAnda.ipynb, lalu jalankan cell berikut untuk menyiapkan dataset (file dibuat otomatis di runtime):

python
data_csv = """tanggal,produk,kategori,qty,harga
2025-01-01,Laptop,Elektronik,2,8500000
2025-01-01,Mouse,Aksesoris,5,150000
2025-01-02,Keyboard,Aksesoris,3,250000
2025-01-02,Monitor,Elektronik,2,2000000
2025-01-03,Printer,Elektronik,1,1500000
2025-01-03,Mouse,Aksesoris,8,150000
2025-02-01,Laptop,Elektronik,1,8500000
2025-02-02,Keyboard,Aksesoris,4,250000
2025-02-03,Monitor,Elektronik,3,2000000
2025-02-03,Mouse,Aksesoris,6,150000
"""

with open("penjualan.csv", "w") as f:
    f.write(data_csv)

print("File penjualan.csv siap digunakan.")

Konsep Singkat

Pandas adalah library Python untuk mengolah data berbentuk tabel. Berbeda dengan sekadar menampilkan data, pada pertemuan ini kita belajar mengendalikan data: memilih baris/kolom secara presisi, menyaring dengan banyak syarat sekaligus, dan menyusun ulang urutannya untuk menjawab pertanyaan bisnis.

Series vs DataFrame

Penting membedakan dua istilah ini:

  • Series adalah data satu dimensi, setara dengan satu kolom.
  • DataFrame adalah tabel dua dimensi, yaitu gabungan beberapa Series.

Saat kita mengambil satu kolom dari DataFrame (misalnya df["harga"]), hasilnya adalah sebuah Series.

Anatomi DataFrame

text
                COLUMNS  ──►  produk     harga
                            +---------+---------+
   INDEX  0  ──►            | Laptop  | 8500000 |   ◄── salah satu baris
          1  ──►            | Mouse   |  150000 |
          2  ──►            | Keyboard|  250000 |
                            +---------+---------+
                                  ▲
                               VALUES
  • Index — label baris (default: 0, 1, 2, ...).
  • Columns — label kolom.
  • Values — isi datanya.

Hubungan dengan Struktur Data Python

Ingat struktur list of dictionary dari pertemuan dasar? Setiap dictionary adalah satu baris, dan setiap key adalah satu kolom. DataFrame adalah versi "bertenaga" dari struktur itu — dengan ribuan operasi siap pakai.

text
List of Dictionary (Python)  →  DataFrame (Pandas)  →  Tabel (Database)

Langkah 1 - Membuat dan Mengenali DataFrame

Setiap penggunaan Pandas dimulai dengan import. pd adalah nama panggilan (alias) yang umum dipakai.

python
import pandas as pd

Series: Pembentuk DataFrame

python
harga = pd.Series([8500000, 150000, 250000], name="harga")
print(harga)
print("Tipe:", type(harga))

Output:

text
0    8500000
1     150000
2     250000
Name: harga, dtype: int64
Tipe: <class 'pandas.core.series.Series'>
Aturan penting: df["harga"] menghasilkan Series (satu kolom), sedangkan df[["harga"]] (kurung siku ganda) menghasilkan DataFrame (tabel satu kolom). Perbedaan ini menentukan operasi apa yang bisa dilakukan setelahnya.

Membuat DataFrame dari Dictionary

Format: kolom → daftar nilai.

python
data = {
    "produk": ["Laptop", "Mouse", "Keyboard"],
    "harga":  [8500000, 150000, 250000],
    "stok":   [10, 50, 30]
}
df_contoh = pd.DataFrame(data)
print(df_contoh)

Output:

text
     produk    harga  stok
0    Laptop  8500000    10
1     Mouse   150000    50
2  Keyboard   250000    30

Membuat DataFrame dari List of Dictionary

Format: tiap dictionary = satu baris. Inilah jembatan langsung dari struktur data Python ke Pandas.

python
records = [
    {"produk": "Laptop", "harga": 8500000},
    {"produk": "Mouse",  "harga": 150000},
]
pd.DataFrame(records)

Atribut Struktur

Atribut ditulis tanpa tanda kurung karena hanya membaca informasi, bukan menjalankan perhitungan.

python
print(df_contoh.shape)     # (baris, kolom)
print(df_contoh.columns)   # nama kolom
print(df_contoh.dtypes)    # tipe data per kolom
print(df_contoh.index)     # label baris

Output:

text
(3, 3)
Index(['produk', 'harga', 'stok'], dtype='object')
produk    object
harga      int64
stok       int64
dtype: object
RangeIndex(start=0, stop=3, step=1)
Atribut Fungsi
df.shape (jumlah baris, jumlah kolom)
df.columns Nama-nama kolom
df.dtypes Tipe data tiap kolom
df.index Label baris

Melihat Sebagian Data

python
df_contoh.head()      # 5 baris pertama
df_contoh.tail()      # 5 baris terakhir
df_contoh.sample(2)   # 2 baris acak

Langkah 2 - Memilih Data dengan .loc dan .iloc

Ini adalah inti pengendalian data di Pandas. Keduanya memilih baris/kolom, tetapi dengan cara berbeda:

Pemilih Berbasis Contoh Arti
.loc label (nama) df.loc[0, "produk"] baris berlabel 0, kolom "produk"
.iloc posisi (angka) df.iloc[0, 1] baris ke-0, kolom ke-1
python
# .iloc — berbasis posisi
print(df_contoh.iloc[0])         # seluruh baris pertama (Series)
print(df_contoh.iloc[0:2])       # dua baris pertama (DataFrame)
print(df_contoh.iloc[0, 1])      # baris 0, kolom 1 -> 8500000

# .loc — berbasis label
print(df_contoh.loc[0, "produk"])                 # -> Laptop
print(df_contoh.loc[0:1, ["produk", "harga"]])    # baris 0-1, kolom terpilih
Catatan: Pada .iloc, 0:2 berarti posisi 0 dan 1 (batas akhir tidak ikut, seperti slicing list). Pada .loc, 0:1 justru menyertakan label 1. Perbedaan kecil ini sering jadi sumber kebingungan, jadi ingat baik-baik.

Langkah 3 - Membaca CSV dan Menangani Tipe Tanggal

Membaca File CSV

Pada praktik nyata, data datang dalam bentuk file. Fungsi pd.read_csv() membaca CSV menjadi DataFrame.

python
import pandas as pd

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

Output:

text
      tanggal    produk    kategori  qty    harga
0  2025-01-01    Laptop  Elektronik    2  8500000
1  2025-01-01     Mouse   Aksesoris    5   150000
2  2025-01-02  Keyboard   Aksesoris    3   250000
3  2025-01-02   Monitor  Elektronik    2  2000000
4  2025-01-03   Printer  Elektronik    1  1500000

Masalah Tersembunyi: Tanggal Terbaca sebagai Teks

Periksa tipe datanya:

python
df.dtypes

Output:

text
tanggal     object
produk      object
kategori    object
qty          int64
harga        int64
dtype: object

Perhatikan: tanggal bertipe object (teks biasa), bukan tanggal. Akibatnya kita tidak bisa mengambil bulan/tahun atau menghitung selisih hari. Ini masalah nyata yang sering luput.

Solusi: Parameter parse_dates

Beri tahu Pandas bahwa kolom tanggal adalah tanggal sejak awal pembacaan:

python
df = pd.read_csv("penjualan.csv", parse_dates=["tanggal"])
print(df.dtypes)

Output:

text
tanggal     datetime64[ns]
produk              object
kategori            object
qty                  int64
harga                int64
dtype: object

Sekarang komponen tanggal bisa digali lewat akses .dt:

python
df["bulan"] = df["tanggal"].dt.month
df[["tanggal", "bulan"]].head(3)

Output:

text
     tanggal  bulan
0 2025-01-01      1
1 2025-01-01      1
2 2025-01-02      1

Parameter read_csv Lain yang Berguna

Parameter Kegunaan
parse_dates=[...] Mengubah kolom menjadi tipe tanggal
usecols=[...] Membaca hanya kolom tertentu (hemat memori)
index_col="kolom" Menjadikan suatu kolom sebagai index
sep=";" Untuk CSV yang dipisah titik koma (umum di Eropa)

Menambah Kolom Turunan

python
df["total"] = df["qty"] * df["harga"]
df.head(3)

Output:

text
     tanggal    produk    kategori  qty    harga  bulan     total
0 2025-01-01    Laptop  Elektronik    2  8500000      1  17000000
1 2025-01-01     Mouse   Aksesoris    5   150000      1    750000
2 2025-01-02  Keyboard   Aksesoris    3   250000      1    750000

Langkah 4 - Menyaring Data (Filtering)

Konsep: Boolean Indexing

Sebuah kondisi pada kolom menghasilkan deretan True/False untuk tiap baris; DataFrame kemudian menampilkan baris yang True.

python
df["qty"] > 4

Output:

text
0    False
1     True
2    False
3    False
4    False
5     True
6    False
7    False
8    False
9     True
Name: qty, dtype: bool

Kondisi Majemuk

Gabungkan kondisi dengan & (DAN), | (ATAU), ~ (BUKAN). Setiap kondisi wajib dibungkus tanda kurung.

python
# Elektronik DAN qty minimal 2
df[(df["kategori"] == "Elektronik") & (df["qty"] >= 2)]

Output:

text
     tanggal   produk    kategori  qty    harga  bulan     total
0 2025-01-01   Laptop  Elektronik    2  8500000      1  17000000
3 2025-01-02  Monitor  Elektronik    2  2000000      1   4000000
8 2025-02-03  Monitor  Elektronik    3  2000000      2   6000000
Operator Arti Padanan logika Python
& DAN and
` ` ATAU or
~ BUKAN not
Error umum: Tanpa tanda kurung — df[df["qty"] >= 2 & df["kategori"] == "Elektronik"] — Python salah membaca urutan operasi dan menghasilkan error. Selalu: df[(kondisi1) & (kondisi2)].

Menyaring Rentang Nilai: between()

python
df[df["harga"].between(200000, 2000000)]

Output:

text
     tanggal    produk    kategori  qty    harga  bulan    total
2 2025-01-02  Keyboard   Aksesoris    3   250000      1   750000
3 2025-01-02   Monitor  Elektronik    2  2000000      1  4000000
4 2025-01-03   Printer  Elektronik    1  1500000      1  1500000
7 2025-02-02  Keyboard   Aksesoris    4   250000      2  1000000
8 2025-02-03   Monitor  Elektronik    3  2000000      2  6000000

Menyaring dari Daftar: isin()

python
df[df["produk"].isin(["Laptop", "Monitor"])]

Menyaring Teks: metode .str

python
df[df["tanggal"].dt.month == 1]        # transaksi bulan Januari
df[df["produk"].str.contains("o")]     # produk yang mengandung huruf 'o'

Alternatif yang Lebih Bersih: query()

query() memungkinkan kondisi ditulis seperti kalimat — cocok untuk filter yang panjang.

python
df.query("kategori == 'Elektronik' and qty >= 2")

Hasilnya identik dengan boolean indexing di atas, tetapi lebih mudah dibaca.

Langkah 5 - Mengurutkan Data (Sorting)

Mengurutkan Satu Kolom

python
df.sort_values("harga", ascending=False).head()

Output:

text
     tanggal   produk    kategori  qty    harga  bulan     total
0 2025-01-01   Laptop  Elektronik    2  8500000      1  17000000
6 2025-02-01   Laptop  Elektronik    1  8500000      2   8500000
3 2025-01-02  Monitor  Elektronik    2  2000000      1   4000000
8 2025-02-03  Monitor  Elektronik    3  2000000      2   6000000
4 2025-01-03  Printer  Elektronik    1  1500000      1   1500000
Penting: sort_values() mengembalikan salinan yang terurut dan tidak mengubah df asli. Untuk menyimpan, tampung ke variabel: df_urut = df.sort_values("harga"). Hindari inplace=True saat masih belajar agar data asli tetap utuh.

Mengurutkan Multi-Level

Urutkan berdasarkan kategori (A→Z), lalu di dalam tiap kategori berdasarkan harga (besar→kecil). Setiap kolom bisa punya arah urut sendiri.

python
df.sort_values(["kategori", "harga"], ascending=[True, False])

Mengambil Nilai Ekstrem dengan Cepat

python
df.nlargest(3, "total")    # 3 transaksi dengan total tertinggi
df.nsmallest(3, "harga")   # 3 transaksi dengan harga terendah

nlargest/nsmallest lebih ringkas daripada sort_values(...).head(n) dan langsung memberi N data teratas/terbawah.

Langkah 6 - Tabel Ringkasan dan Analisis Produk

Daripada menjawab tiap pertanyaan dengan perintah terpisah, kita bangun satu tabel ringkasan per produk, lalu jawab semua pertanyaan dari sana. Pendekatan ini lebih rapi dan mudah dikembangkan.

Persiapan

python
import pandas as pd

df = pd.read_csv("penjualan.csv", parse_dates=["tanggal"])
df["total"] = df["qty"] * df["harga"]

Membangun Ringkasan dengan agg()

groupby().agg() memungkinkan kita menghitung beberapa ringkasan sekaligus dan memberi nama kolomnya:

python
ringkasan = df.groupby("produk").agg(
    total_qty=("qty", "sum"),
    total_penjualan=("total", "sum"),
    jumlah_transaksi=("produk", "count"),
    harga_satuan=("harga", "first")
)
print(ringkasan)

Output:

text
          total_qty  total_penjualan  jumlah_transaksi  harga_satuan
produk
Keyboard          7          1750000                 2        250000
Laptop            3         25500000                 2       8500000
Monitor           5         10000000                 2       2000000
Mouse            19          2850000                 3        150000
Printer           1          1500000                 1       1500000

Satu tabel ini sudah memuat semua yang kita butuhkan.

1. Produk Terlaris (qty terbanyak)

python
terlaris = ringkasan["total_qty"].idxmax()
print("Produk terlaris:", terlaris, "-", ringkasan.loc[terlaris, "total_qty"], "unit")

Output:

text
Produk terlaris: Mouse - 19 unit

2. Produk Termurah (harga satuan terendah)

python
termurah = ringkasan["harga_satuan"].idxmin()
print("Produk termurah:", termurah, "-", ringkasan.loc[termurah, "harga_satuan"])

Output:

text
Produk termurah: Mouse - 150000

3. Produk Termahal (harga satuan tertinggi)

python
termahal = ringkasan["harga_satuan"].idxmax()
print("Produk termahal:", termahal, "-", ringkasan.loc[termahal, "harga_satuan"])

Output:

text
Produk termahal: Laptop - 8500000
Konsep kunci: idxmax()/idxmin() mengembalikan label index (di sini nama produk) yang memiliki nilai tertinggi/terendah. Karena tabel ringkasan ber-index produk, jawabannya langsung berupa nama produk — tanpa perlu mengurutkan terlebih dahulu.

Ringkasan Hasil

python
print("=== ANALISIS PRODUK ===")
print("Terlaris :", ringkasan["total_qty"].idxmax())
print("Termurah :", ringkasan["harga_satuan"].idxmin())
print("Termahal :", ringkasan["harga_satuan"].idxmax())

Output:

text
=== ANALISIS PRODUK ===
Terlaris : Mouse
Termurah : Mouse
Termahal : Laptop
Temuan untuk didiskusikan: Mouse termurah sekaligus terlaris (19 unit), tetapi penyumbang penjualan rupiah terbesar justru Laptop (Rp25.500.000) meski hanya laku 3 unit. Volume tinggi belum tentu berarti pendapatan tinggi — diskusikan implikasinya bagi pemilik toko.

Pengujian

Periksa hasil praktikum dengan memastikan output sesuai berikut:

  1. df.shape setelah membaca CSV dan menambah kolom bulan + total menghasilkan (10, 7).
  2. df.dtypes menunjukkan kolom tanggal bertipe datetime64[ns].
  3. Tabel ringkasan memuat 5 baris produk dengan total_qty Mouse = 19 dan harga_satuan Laptop = 8500000.
  4. Hasil analisis: terlaris = Mouse, termurah = Mouse, termahal = Laptop.

Verifikasi cepat secara otomatis:

python
assert df.shape == (10, 7)
assert ringkasan.loc["Mouse", "total_qty"] == 19
assert ringkasan["harga_satuan"].idxmax() == "Laptop"
print("Semua pengujian lolos.")

Troubleshooting

Masalah Penyebab Solusi
FileNotFoundError: penjualan.csv File belum dibuat di runtime aktif Jalankan ulang cell pada bagian Persiapan
KeyError: 'nama_kolom' Nama kolom salah ketik Periksa daftar kolom dengan df.columns
Filter majemuk menghasilkan error Lupa tanda kurung tiap kondisi Tulis df[(kondisi1) & (kondisi2)]
.dt menghasilkan error Kolom tanggal masih bertipe object Baca ulang dengan parse_dates=["tanggal"]
Hasil pengurutan tidak tersimpan sort_values mengembalikan salinan Tampung ke variabel: df2 = df.sort_values(...)

Tugas Praktikum

Buat laporan (format PDF) yang berisi:

  1. Identitas: Nama dan NIM.
  2. Tabel ringkasan per produk hasil agg().
  3. Produk terlaris, termurah, dan termahal.
  4. Produk penyumbang penjualan rupiah tertinggi — petunjuk: ringkasan["total_penjualan"].idxmax().
  5. Total penjualan per bulan — petunjuk: df.groupby(df["tanggal"].dt.month)["total"].sum().
  6. Produk terlaris khusus bulan Januari — petunjuk: gabungkan filter df["tanggal"].dt.month == 1 dengan groupby, lalu idxmax(). Bandingkan dengan terlaris keseluruhan.
  7. Kesimpulan dan interpretasi temuan.
Tips: ekspor notebook ke PDF melalui menu File → Print → Save as PDF.

Kesimpulan

Pada pertemuan ini mahasiswa menguasai fondasi Pandas secara menyeluruh: memahami anatomi DataFrame dan Series, memilih data presisi dengan .loc/.iloc, membaca CSV beserta penanganan tipe tanggal, menyaring data dengan kondisi majemuk hingga query(), dan mengurutkan data secara multi-level. Puncaknya, mahasiswa membangun tabel ringkasan dengan agg() untuk menjawab pertanyaan bisnis — produk terlaris, termurah, dan termahal — serta menafsirkan perbedaan antara volume dan nilai penjualan. Kemampuan membentuk tabel ringkasan ini menjadi pijakan untuk visualisasi data pada pertemuan berikutnya.