Hampir semua chapter sejauh ini menulis rumus kolom dengan dua gaya: string seperti df.query("unit > 100") atau lambda seperti assign(omzet=lambda d: d["unit"] * d["harga"]). Keduanya bekerja, tetapi keduanya punya celah — string tidak diperiksa saat ditulis, dan lambda menyulitkan pembacaan saat rumus dipakai ulang di beberapa tempat. pandas 3.0 memperkenalkan pd.col(): fungsi yang merujuk kolom dan mengembalikan objek Expression yang bisa dijumlah, dibandingkan, dan diteruskan ke method yang menerima callable. Chapter ini membahas pd.col() pada assign(), pada seleksi loc, serta perbandingannya dengan jalur lambda.

Ekspresi Pertama #

pd.col("unit") * pd.col("harga") tidak langsung menghitung apa pun; hasilnya objek Expression yang menggambarkan operasi tersebut. Saat ekspresi diteruskan ke assign(), pandas mengevaluasinya terhadap DataFrame dan menghasilkan kolom baru omzet. Operator Python yang lazim — +, -, *, /, perbandingan >= — semuanya bekerja pada Expression, sehingga rumus bisa ditulis hampir persis seperti rumus matematikanya. Perilaku ini menempatkan rumus sebagai data: satu variabel ekspresi bisa didefinisikan di atas, lalu dipakai ulang di beberapa method tanpa menulis ulang lambda.

python
import pandas as pd

penjualan = pd.DataFrame(
    {
        "produk": ["Kopi", "Teh", "Gula", "Susu"],
        "unit": [120, 85, 60, 200],
        "harga": [45_000, 42_000, 32_000, 24_000],
    }
)

# pd.col() merujuk kolom dan membangun ekspresi
dengan_omzet = penjualan.assign(omzet=pd.col("unit") * pd.col("harga"))
print(dengan_omzet)

# ekspresi menjadi mask boolean yang bisa dipakai loc
omzet_besar = pd.col("unit") * pd.col("harga") >= 3_000_000
print("\nproduk dengan omzet >= 3 juta:")
print(penjualan.loc[omzet_besar, ["produk"]])

# hasil identik dengan jalur lambda
via_lambda = penjualan.assign(omzet=lambda d: d["unit"] * d["harga"])
print("\nekspresi == lambda:", via_lambda.equals(dengan_omzet))

Output yang Dihasilkan:

text
  produk  unit  harga    omzet
0   Kopi   120  45000  5400000
1    Teh    85  42000  3570000
2   Gula    60  32000  1920000
3   Susu   200  24000  4800000

produk dengan omzet >= 3 juta:
  produk
0   Kopi
1    Teh
3   Susu

ekspresi == lambda: True

Mari kita telaah baris-baris kuncinya:

  1. Baris 10-10: assign(omzet=pd.col("unit") * pd.col("harga")) menghasilkan kolom omzet yang nilainya identik dengan perkalian dua kolom.
  2. Baris 13-16: perbandingan >= pada ekspresi menghasilkan mask boolean, dan loc[omzet_besar, ["produk"]] menampilkan tiga produk dengan omzet minimal tiga juta.
  3. Baris 19-20: hasil ekspresi dibandingkan dengan jalur lambda lewat equals() dan keduanya True — dua gaya penulisan, satu hasil.

Ekspresi vs Lambda #

Jalur lambda lambda d: d["unit"] * d["harga"] tetap valid dan tetap diperlukan saat logikanya rumit — pemanggilan fungsi kustom, np.where, atau akses kolom sementara. Keunggulan pd.col() terletak pada rumus yang sering dipakai ulang: ekspresi bisa disimpan sebagai konstanta modul, dibagikan antar fungsi, dan dibaca tanpa melacak isi d. Nama kolom di dalam pd.col() juga diperiksa saat ekspresi dievaluasi, sehingga salah ketik melempar KeyError yang jelas alih-alih gagal diam-diam di jalur string. Untuk pipeline yang berisi banyak rumus bisnis, konsistensi satu gaya membuat review kode jauh lebih cepat.

Batas Ekspresi #

Expression pada pandas 3.0 baru menghuni jalur callable: assign(), mask loc, dan semacamnya. Method yang menerima string seperti query() dan eval() masih memakai sintaks stringnya sendiri, dan window seperti rolling() belum menerima ekspresi. Praktik yang sehat adalah menetapkan batas: ekspresi pd.col() untuk rumus yang dipakai ulang dan perlu diperiksa, string untuk ad-hoc interaktif, lambda untuk logika yang tidak bisa dinyatakan sebagai operator. Ketiganya hidup berdampingan tanpa saling menggantikan.

Chapter ini menambahkan cara baru menulis rumus; cara baru mengubah data setelah terpilih dibahas berikutnya. Chapter selanjutnya membahas Copy-on-Write, aturan memori yang menentukan mengapa chained assignment tidak lagi mengubah data di pandas 3.0.

Dokumentasi resmi yang relevan: pandas.col sebagai definisi fungsi dan batasannya, pandas.DataFrame.assign untuk jalur callable yang sudah lama, dan What’s new in pandas 3.0.0 yang memperkenalkan ekspresi kolom.