Sebuah laporan penjualan biasanya melewati banyak tahapan: menyaring baris yang tidak relevan, menambahkan kolom perhitungan, lalu merapikan hasil. Apabila setiap tahap ditulis terpisah, notebook kita penuh variabel perantara; apabila dirangkai method demi method, tidak ada tempat alami untuk menyisipkan fungsi buatan sendiri. Method pipe() mengatasi kedua masalah itu dengan memasukkan fungsi bebas ke dalam rantai DataFrame. Chapter ini membahas mekanisme pipe(), cara mengirim argumen ke fungsinya, dan cara menyusun pipeline yang nyaman dibaca.

Mekanisme pipe() #

Aturan pipe() sederhana: df.pipe(fungsi, argumen_lain) persis sama dengan fungsi(df, argumen_lain). pandas mengambil DataFrame sebagai argumen pertama fungsi, lalu memakai nilai balik fungsi tersebut sebagai objek untuk langkah berikutnya dalam rantai. Karena hasilnya kembali berupa DataFrame, kita bebas merangkai method apa pun setelahnya. Data asli tidak berubah selama fungsi kita tidak memodifikasinya, sejalan dengan perilaku Copy-on-Write di pandas 3.0.

python
import pandas as pd


def saring_harga(df, kolom, batas):
    return df[df[kolom] <= batas]


def tambah_total(df):
    return df.assign(total=df["harga"] * df["jumlah"])


pesanan = pd.DataFrame(
    {
        "produk": ["Kopi Gayo", "Teh Melati", "Gula Aren", "Kopi Toraja"],
        "harga": [85000, 32000, 24000, 90000],
        "jumlah": [12, 30, 25, 5],
    }
)

hasil = pesanan.pipe(saring_harga, kolom="harga", batas=88000).pipe(tambah_total)

print(pesanan)
print()
print(hasil)

Output yang Dihasilkan:

text
        produk  harga  jumlah
0    Kopi Gayo  85000      12
1   Teh Melati  32000      30
2    Gula Aren  24000      25
3  Kopi Toraja  90000       5

       produk  harga  jumlah    total
0   Kopi Gayo  85000      12  1020000
1  Teh Melati  32000      30   960000
2   Gula Aren  24000      25   600000

Mari kita telaah apa yang terjadi pada kode di atas:

  1. Baris 4-5: mendefinisikan saring_harga(); fungsi menerima DataFrame dan dua argumen saringan, lalu mengembalikan DataFrame hasil seleksi baris.
  2. Baris 8-9: mendefinisikan tambah_total(); fungsi menerima DataFrame dan mengembalikan versi baru dengan kolom total, memakai assign() dari Chapter sebelumnya.
  3. Baris 12-18: membangun DataFrame pesanan berisi empat produk.
  4. Baris 20: pipe() pertama memanggil saring_harga(pesanan, kolom="harga", batas=88000); pipe() kedua memanggil tambah_total() dengan hasil saringan tadi sebagai argumennya.
  5. Baris 22-24: perintah print menampilkan pesanan asli yang tetap empat baris dan hasil yang tinggal tiga baris ditambah kolom total.

Perhatikan urutan eksekusinya: saringan dulu, penambahan kolom kemudian. Baris Kopi Toraja dengan harga 90000 hilang pada tahap pertama, sehingga tambah_total() hanya menghitung tiga baris tersisa. Apabila urutan kedua pipe() dibalik, kolom total tetap dihitung untuk empat baris dan barisnya baru disaring setelah itu — jumlah akhirnya sama, namun isi kolom total untuk data mentah menjadi berbeda.

Mengirim Argumen ke Fungsi #

Semua argumen tambahan setelah nama fungsi diteruskan pipe() apa adanya. Argumen posisi disalin sesuai urutan penulisannya, sedangkan argumen kata kunci seperti kolom= dan batas= diserahkan beserta namanya. Dengan sifat itu, satu fungsi dapat dipakai ulang untuk beberapa tahap dengan saringan berbeda: pipe(saring_harga, kolom="jumlah", batas=20) menyaring berdasarkan kolom lain tanpa perlu membuat fungsi baru. Pola ini menjaga jumlah fungsi kecil, karena perbedaan kebutuhan ditangani oleh argumen, bukan oleh salinan fungsi.

Pipeline yang Terbaca dari Atas ke Bawah #

Keuntungan terbesar pipe() ada pada bentuk akhir kode. Tanpa pipe(), komposisi fungsi menjadi bersarang seperti tambah_total(saring_harga(pesanan, ...)), dan kedalaman bersarang itu bertambah setiap kali tahapan baru muncul. Dengan pipe(), setiap tahap menempati satu potongan rantai dalam urutan eksekusi, sehingga pembaca menelusuri alur dari atas ke bawah seperti membaca resep.

PenulisanWujudnya
Bersarang: tambah_total(saring_harga(pesanan, ...))Semakin sulit dibaca saat tahapan bertambah
Variabel perantara: df1 = saring_harga(...), df2 = tambah_total(df1)Banyak nama sementara yang mudah tercampur
Rantai: pesanan.pipe(saring_harga, ...).pipe(tambah_total)Satu alur dengan urutan eksekusi yang jelas

Dokumentasi pandas.DataFrame.pipe merinci parameter pipe(), termasuk dukungan argumen kata kunci yang kita pakai di atas. Halaman Essential basic functionality menempatkan pipe() sebagai bagian dari pola function application, berdampingan dengan apply() dan map() yang sudah kita pelajari sebelumnya.

Rantai pipe() yang panjang sering kali berakhir pada perhitungan statistik per kelompok, misalnya rata-rata skor setiap kelompok belajar. Di sanalah dua method saudara, aggregate() dan transform(), bermain peran dengan cara yang sangat berbeda; kita bandingkan keduanya pada Chapter berikutnya.