Array NumPy menghitung cepat, tetapi data nyata jarang sekata. Catatan penjualan Toko Kopi Kita membawa tanggal (teks), nama produk (teks), nama kota (teks), jumlah (bilangan), dan harga (bilangan) dalam satu tabel — dan tabel itulah bentuk data yang paling sering kita terima di dunia kerja. Pandas adalah library yang dibangun untuk tabel: membacanya dari berkas, memeriksanya, memilih bagiannya, menyaring barisnya, dan meringkasnya per kelompok. Pada chapter ini kita berkenalan dengan dua struktur intinya — Series dan DataFrame — lalu mempraktikkan alur kerja lengkap pada berkas penjualan.csv yang berisi 15 transaksi sepekan.

Series dan DataFrame: Satu Kolom dan Satu Tabel #

Series adalah satu kolom berlabel: deret nilai plus daftar label yang disebut index, satu per baris. DataFrame adalah tabel utuh — secara teknis, kumpulan Series yang berbagi index yang sama. Kita buat keduanya secara eksplisit dulu:

python
import pandas as pd

# Series: satu kolom angka yang setiap barisnya berlabel (index)
jumlah = pd.Series(
    data=[85, 51, 28],
    index=["kopi susu", "matcha latte", "teh tawar"],
    name="terjual (gelas)",
)
print(jumlah)
print()
print("Akses dengan label :", jumlah["matcha latte"])

Output yang Dihasilkan:

text
kopi susu       85
matcha latte    51
teh tawar       28
Name: terjual (gelas), dtype: int64

Akses dengan label : 51

Label kiri pada keluaran di atas adalah index dan angka kanannya nilai Series; name menjadi nama kolom saat Series ini dipakai di dalam DataFrame. Akses jumlah["matcha latte"] menuju baris berdasarkan labelnya, bukan berdasarkan posisi — inilah perbedaan paling terasa dibanding array NumPy yang hanya mengenal posisi.

DataFrame paling mudah dibangun dari dictionary — setiap kunci menjadi nama kolom — atau dari list of dictionary yang tiap anggotanya menjadi satu baris:

python
import pandas as pd

# DataFrame dari dictionary: {nama kolom: daftar nilai}
menu = pd.DataFrame({
    "minuman": ["kopi susu", "matcha latte", "teh tawar", "cokelat panas"],
    "harga": [24, 28, 20, 30],        # ribu rupiah
    "volume_ml": [300, 250, 200, 400],
})
print(menu)
print()

# DataFrame dari list of dictionary: satu dictionary per baris
pesanan = pd.DataFrame([
    {"produk": "kopi susu", "jumlah": 2},
    {"produk": "teh tawar", "jumlah": 1},
])
print(pesanan)

Output yang Dihasilkan:

text
         minuman  harga  volume_ml
0      kopi susu     24        300
1   matcha latte     28        250
2      teh tawar     20        200
3  cokelat panas     30        400

      produk  jumlah
0  kopi susu       2
1  teh tawar       1

Perhatikan kolom paling kiri pada kedua tabel: angka 0, 1, 2, ... adalah index otomatis yang diberikan pandas ketika kita tidak menetapkan label sendiri. Bentuk dictionary cocok saat data tersusun per kolom, sedangkan list of dictionary cocok saat data mengalir per baris — misalnya hasil pembacaan berkas.

Membaca File CSV dengan read_csv #

Sumber data paling umum adalah berkas CSV (comma-separated values): teks dengan satu baris data per baris teks dan tanda koma sebagai pemisah kolom. Kita pakai berkas penjualan.csv berikut — lima kolom, lima belas transaksi pekan 6-12 Januari 2025 di dua cabang:

csv
tanggal,produk,kota,jumlah,harga
2025-01-06,kopi susu,Bandung,12,24000
2025-01-06,matcha latte,Bandung,8,28000
2025-01-06,teh tawar,Bandung,5,20000
2025-01-07,kopi susu,Bandung,15,24000
2025-01-07,teh tawar,Bandung,6,20000
2025-01-08,kopi susu,Surabaya,10,24000
2025-01-08,matcha latte,Surabaya,9,28000
2025-01-09,kopi susu,Surabaya,14,24000
2025-01-09,matcha latte,Surabaya,17,28000
2025-01-09,teh tawar,Surabaya,4,20000
2025-01-10,kopi susu,Bandung,18,24000
2025-01-10,matcha latte,Bandung,7,28000
2025-01-11,kopi susu,Surabaya,16,24000
2025-01-11,teh tawar,Surabaya,13,20000
2025-01-12,matcha latte,Bandung,10,28000

Membacanya membutuhkan satu fungsi — pd.read_csv() dengan nama berkas relatif terhadap folder kerja:

python
import pandas as pd

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

print("Bentuk (baris, kolom) :", df.shape)
print(df.head())

Output yang Dihasilkan:

text
Bentuk (baris, kolom) : (15, 5)
      tanggal        produk     kota  jumlah  harga
0  2025-01-06     kopi susu  Bandung      12  24000
1  2025-01-06  matcha latte  Bandung       8  28000
2  2025-01-06     teh tawar  Bandung       5  20000
3  2025-01-07     kopi susu  Bandung      15  24000
4  2025-01-07     teh tawar  Bandung       6  20000

df adalah nama variabel kebiasaan untuk DataFrame. df.shape memuat ukuran (15, 5) seperti shape pada array NumPy, dan df.head() menampilkan lima baris pertama — cara tercepat memastikan berkas terbaca dengan benar sebelum diproses lebih jauh.

Inspeksi Cepat: info dan describe #

Sebelum menganalisis, kita periksa dulu apa yang sebenarnya kita pegang: berapa baris, kolom apa saja, tipe data apa, dan bagaimana sebaran angkanya. Dua alatnya adalah df.info() dan df.describe():

python
import pandas as pd

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

df.info()
print()
print(df.describe())

Output yang Dihasilkan:

text
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 5 columns):
 #   Column   Non-Null Count  Dtype 
---  ------   --------------  ----- 
 0   tanggal  15 non-null     object
 1   produk   15 non-null     object
 2   kota     15 non-null     object
 3   jumlah   15 non-null     int64 
 4   harga    15 non-null     int64 
dtypes: int64(2), object(3)
memory usage: 732.0+ bytes

          jumlah         harga
count  15.000000     15.000000
mean   10.933333  24266.666667
std     4.479583   3195.234547
min     4.000000  20000.000000
25%     7.500000  22000.000000
50%    10.000000  24000.000000
75%    14.500000  28000.000000
max    18.000000  28000.000000

Mari kita baca keluaran info() baris demi baris:

  1. RangeIndex: 15 entries: 15 baris berindex 0 sampai 14 — cocok dengan shape dan berarti tidak ada baris yang gagal dibaca.
  2. Kolom Non-Null Count: setiap kolom mencatat 15 nilai non-kosong. Kolom yang mencatat kurang dari 15 menandakan adanya missing values — topik besar yang kita bahas tuntas pada bab pembersihan data.
  3. Kolom Dtype: tanggal, produk, dan kota terbaca sebagai object (teks), sedangkan jumlah dan harga sebagai int64. Pada dasarnya setiap kolom DataFrame adalah array NumPy dengan dtype sendiri — itulah jembatan antara kedua library.
  4. describe() meringkas hanya kolom numerik: count jumlah data, mean rata-rata, std simpangan baku, lalu min, kuartil 25%/50%/75%, dan max. Nilai 50% adalah median — separuh transaksi menjual 10 gelas atau kurang. Statistik kolom harga perlu dibaca hati-hati karena hanya ada tiga harga berbeda (20, 24, dan 28 ribu rupiah): rata-ratanya menggambarkan campuran produk yang terjual, bukan harga satu menu tertentu.

Baris memory usage: 732.0+ bytes melaporkan perkiraan pemakaian memori; tanda plus menandakan angka tersebut masih bisa bertambah bila ada kolom bertipe object yang panjang.

Memilih Kolom dan Menyaring Baris dengan Mask Boolean #

Dua kebutuhan paling sering: mengambil sebagian kolom, dan mengambil baris yang memenuhi syarat. Pemilihan kolom memakai kurung siku seperti pada dictionary; penyaringan baris memakai mask boolean — Series berisi True/False yang menentukan baris mana yang lolos:

python
import pandas as pd

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

# 1. Memilih kolom: satu kolom -> Series, beberapa kolom -> DataFrame
print("Produk unik :", df["produk"].unique().tolist())
print(df[["tanggal", "produk", "jumlah"]].head(3))
print()

# 2. Filter baris dengan mask boolean
mask_bandung = df["kota"] == "Bandung"
print("Mask seluruhnya :")
print(mask_bandung.tolist())
print("Baris Bandung :", len(df[mask_bandung]))
print(df[mask_bandung][["tanggal", "produk", "jumlah"]])
print()

# 3. Kombinasi kondisi: & (dan), | (atau) — selalu beri tanda kurung
mask_laris = (df["kota"] == "Surabaya") & (df["jumlah"] >= 14)
print(df[mask_laris][["tanggal", "produk", "jumlah"]])

Output yang Dihasilkan:

text
Produk unik : ['kopi susu', 'matcha latte', 'teh tawar']
      tanggal        produk  jumlah
0  2025-01-06     kopi susu      12
1  2025-01-06  matcha latte       8
2  2025-01-06     teh tawar       5

Mask seluruhnya :
[True, True, True, True, True, False, False, False, False, False, True, True, False, False, True]
Baris Bandung : 8
       tanggal        produk  jumlah
0   2025-01-06     kopi susu      12
1   2025-01-06  matcha latte       8
2   2025-01-06     teh tawar       5
3   2025-01-07     kopi susu      15
4   2025-01-07     teh tawar       6
10  2025-01-10     kopi susu      18
11  2025-01-10  matcha latte       7
14  2025-01-12  matcha latte      10

       tanggal        produk  jumlah
7   2025-01-09     kopi susu      14
8   2025-01-09  matcha latte      17
12  2025-01-11     kopi susu      16

Tiga pola pada contoh di atas:

  1. Pemilihan kolom: df["produk"] mengembalikan satu Series, sedangkan df[["tanggal", "produk", "jumlah"]] dengan list di dalam kurung mengembalikan DataFrame baru berisi tiga kolom tersebut. Method .unique() memangkas Series menjadi daftar nilai uniknya.
  2. Mask boolean: perbandingan df["kota"] == "Bandung" menghasilkan Series 15 True/False — lima pertama True, lima berikutnya False karena baris 5 sampai 9 adalah Surabaya, dan seterusnya. Menuliskan df[mask_bandung] berarti “pertahankan baris yang True saja”, sehingga tersisa 8 baris Bandung.
  3. Kombinasi kondisi: (df["kota"] == "Surabaya") & (df["jumlah"] >= 14) menyaring 3 baris — transaksi Surabaya dengan minimal 14 gelas.

Kolom Baru, groupby, dan sort_values #

Alur analisis biasanya ditutup tiga langkah: menambah kolom turunan, meringkas per kelompok, lalu mengurutkan hasilnya. Ketiganya berpatungan pada satu blok berikut — dan angka totalnya akan terasa akrab:

python
import pandas as pd

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

# Kolom baru: pendapatan = jumlah x harga (element-wise, gaya NumPy)
df["pendapatan"] = df["jumlah"] * df["harga"]

# Agregat per produk: total jumlah dan pendapatan
per_produk = df.groupby("produk")[["jumlah", "pendapatan"]].sum()
print(per_produk)
print()

# Lima transaksi dengan jumlah terbanyak
top5 = df.sort_values("jumlah", ascending=False).head(5)
print(top5[["tanggal", "produk", "kota", "jumlah"]])

Output yang Dihasilkan:

text
              jumlah  pendapatan
produk                          
kopi susu         85     2040000
matcha latte      51     1428000
teh tawar         28      560000

       tanggal        produk      kota  jumlah
10  2025-01-10     kopi susu   Bandung      18
8   2025-01-09  matcha latte  Surabaya      17
12  2025-01-11     kopi susu  Surabaya      16
3   2025-01-07     kopi susu   Bandung      15
7   2025-01-09     kopi susu  Surabaya      14

Mari kita bedah tiga langkahnya:

  1. Kolom baru: df["jumlah"] * df["harga"] mengalikan dua Series element-wise — persis perilaku array NumPy pada chapter sebelumnya — dan menugaskannya ke kolom pendapatan langsung menambah kolom baru pada tabel.
  2. groupby("produk"): memecah tabel menjadi kelompok per produk, meringkas tiap kelompok dengan .sum() pada kolom ["jumlah", "pendapatan"], lalu menggabungkan hasilnya. Total jumlah 85, 51, dan 28 persis angka Series pertama kita di awal chapter; kolom pendapatan menambahkan 85 x 24.000 = 2.040.000 untuk kopi susu, dan seterusnya.
  3. sort_values("jumlah", ascending=False): mengurutkan baris dari jumlah terbanyak, lalu .head(5) memotong lima teratas — dipimpin transaksi 18 gelas di Bandung dan 17 gelas matcha latte di Surabaya. Urutan index yang tampak berantakan (10, 8, 12, 3, 7) mengingatkan bahwa index adalah label baris asal, bukan posisi hasil urut.

Rangkuman #

  • Series = satu kolom berlabel (index); DataFrame = tabel berisi kumpulan Series berindex sama; keduanya dibangun dari dictionary maupun list of dictionary.
  • pd.read_csv("berkas.csv") memuat tabel; df.shape, df.head(), df.info(), dan df.describe() adalah paket inspeksi pertama sebelum analisis.
  • df.info() memperlihatkan jumlah baris, kolom, Non-Null Count, dan Dtype tiap kolom; describe() meringkas kolom numerik dengan mean, std, dan kuartil.
  • Pemilihan kolom memakai df["kolom"] dan df[[...]]; penyaringan baris memakai mask boolean df[df["kota"] == "Bandung"], digabung dengan &/| dan tanda kurung.
  • Kolom baru dihitung element-wise; groupby meringkas per kelompok; sort_values mengurutkan hasil.

Tabel sudah terbaca, terinspeksi, dan teringkas menjadi angka-angka yang bermakna. Langkah terakhir pada alur kerja Python ini adalah mengubah angka menjadi gambar yang bisa dibaca sekilas oleh mata — mulai dari diagram batang hingga diagram garis. Kita tutup Section dengan library ketiga, matplotlib, pada chapter Dasar Matplotlib .

Referensi #

  1. Pandas — Getting Started Tutorials — tur resmi pertama: membuat DataFrame, membaca CSV, dan operasi dasar.
  2. Pandas — pandas.read_csv — rujukan lengkap parameter read_csv.
  3. Pandas — DataFrame.groupby — mekanisme pengelompokan dan agregasi.