Lewati ke konten utama

Pandas .apply(): Apa Fungsinya, Kapan Bermanfaat, dan Alternatif yang Lebih Cepat

Pelajari apa itu Python pandas .apply dan cara menggunakannya untuk DataFrame. Pelajari cara mengiterasi DataFrame menggunakan fungsi .apply() hari ini!
Diperbarui 28 Sep 2026  · 5 mnt Baca

Jelajahi bersama AI

ChatGPTClaudePerplexity

Banyak orang menggunakan .apply() untuk “menghindari loop” dan berharap ini cepat serta mudah. Dalam praktiknya, .apply(axis=1) per baris tetaplah loop di level Python. Ini bisa lambat pada data besar, dan terkadang mengembalikan bentuk yang tidak Anda harapkan. Solusinya sederhana: gunakan operasi vektorisasi pandas/NumPy untuk tugas umum, dan gunakan .apply() hanya untuk logika yang benar-benar membutuhkan beberapa kolom.

Panduan ini menunjukkan cara kerja .apply() saat ini, menyoroti jebakan umum, dan menyediakan pola siap pakai yang lebih cepat dan lebih jelas.

Apa Itu DataFrame.apply() dan Series.apply()?

DataFrame.apply(func, axis=0) secara bawaan memanggil func pada tiap kolom. Dengan axis=1, ia memanggil func pada tiap baris. Series.apply(func) memanggil func pada tiap elemen (atau seluruh Series, tergantung tanda tangan fungsi pada versi terbaru).

  • Per baris vs. per kolom: axis=1 berarti “per baris.” axis=0 (bawaan) berarti “per kolom.”
  • Aturan bentuk keluaran (pandas ≥0,23): Jika fungsi Anda mengembalikan skalar per baris/kolom, Anda mendapatkan sebuah Series. Jika mengembalikan Series atau dict, pandas akan mengembangkan kunci-kunci tersebut menjadi sebuah DataFrame. Jika mengembalikan list/array, Anda akan mendapatkan Series berisi list kecuali Anda menetapkan result_type='expand'.
  • Error yang lebih ketat (pandas ≥2.0): Panjang mirip-list yang tidak cocok kini memunculkan error alih-alih diam-diam menghasilkan hasil yang tidak konsisten.

Pilihan Utama yang Disarankan: Operasi Tervektorisasi

Sebagian besar tugas yang melibatkan penggabungan atau transformasi kolom lebih cepat dan lebih jelas dengan ekspresi tervektorisasi atau metode bawaan. Contoh berikut menghitung selisih run sebuah tim bisbol tanpa .apply().

import pandas as pd

team_stats = pd.DataFrame({
    "Team": ["ARI", "ATL", "BAL"],
    "League": ["NL", "NL", "AL"],
    "Year": [2012, 2012, 2012],
    "RunsScored": [734, 700, 712],
    "RunsAllowed": [688, 600, 705],
    "Wins": [81, 94, 93],
    "Games": [162, 162, 162],
    "Playoffs": [0, 1, 1],
})

# Vectorized: fast and idiomatic
team_stats["RunDiff"] = team_stats["RunsScored"] - team_stats["RunsAllowed"]
print(team_stats[["Team", "RunsScored", "RunsAllowed", "RunDiff"]])

.apply() Per Baris Saat Anda Benar-Benar Membutuhkannya

Gunakan .apply(axis=1) ketika logika Anda benar-benar melibatkan beberapa kolom dan tidak mudah divektorisasi (misalnya, aturan kondisional yang bergantung pada beberapa field).

hitung nilai turunan dari beberapa kolom

Pola ini menghitung nilai per baris menggunakan beberapa masukan. Pendekatan tervektorisasi di atas tetap lebih disukai, namun ini menunjukkan penggunaan per baris yang benar dan opsi yang memengaruhi kecepatan serta keluaran.

def compute_run_diff(row):
    # Treat the row as read-only; return a scalar
    return row["RunsScored"] - row["RunsAllowed"]

# Row-wise apply (Python-level loop; can be slow on large data)
team_stats["RunDiff_apply"] = team_stats.apply(compute_run_diff, axis=1)

Jika fungsi bersifat numerik dan hanya membutuhkan array mentah, memberikan argumen raw=True melewati sebagian overhead pandas dengan menyediakan array NumPy ke fungsi Anda.

import numpy as np

def compute_run_diff_raw(values):
    # values is a NumPy array when raw=True
    # Order matches the column order we select
    rs, ra = values
    return rs - ra

team_stats["RunDiff_raw"] = team_stats[["RunsScored", "RunsAllowed"]].apply(
    compute_run_diff_raw, axis=1, raw=True
)

verifikasi masukan fungsi sekali

Saat saya memasang fungsi baris baru, saya mencetak satu baris sekali untuk memastikan apa yang diteruskan.

def debug_row(row):
    # Print the first row only
    if row.name == team_stats.index[0]:
        print("Example row:", row.to_dict())
    return 0

_ = team_stats.apply(debug_row, axis=1)

Studi Kasus: Penjumlahan, Total Musim, dan Flag Teks

Diberikan statistik Rays per tahun, utamakan metode bawaan dan alat se-elemen dibanding .apply() bila memungkinkan.

rays_by_year = pd.DataFrame(
    {
        "Year": [2012, 2011, 2010, 2009, 2008],
        "RunsScored": [697, 707, 802, 803, 774],
        "RunsAllowed": [577, 614, 649, 754, 671],
        "Wins": [90, 91, 96, 84, 97],
        "Playoffs": [0, 1, 1, 0, 1],
    }
).set_index("Year")

dapatkan jumlah kolom secara efisien

Gunakan DataFrame.sum() alih-alih .apply(sum). Lebih cepat dan lebih jelas.

# Preferred
totals = rays_by_year.sum(axis=0)
print(totals)

# If you must use apply (not recommended here)
totals_apply = rays_by_year.apply(sum, axis=0)

hitung total run yang dicetak dalam satu musim

Gunakan aritmetika tervektorisasi antar kolom; tidak perlu .apply().

rays_by_year["TotalRuns"] = rays_by_year["RunsScored"] + rays_by_year["RunsAllowed"]
print(rays_by_year[["RunsScored", "RunsAllowed", "TotalRuns"]].head())

ubah flag 0/1 menjadi teks

Utamakan Series.map() atau replace() untuk transformasi se-elemen pada satu kolom.

# Using map with a dict
rays_by_year["PlayoffsText"] = rays_by_year["Playoffs"].map({0: "No", 1: "Yes"})

# Equivalent with replace
rays_by_year["PlayoffsText2"] = rays_by_year["Playoffs"].replace({0: "No", 1: "Yes"})

Kendalikan Bentuk Keluaran dari .apply()

Saat fungsi Anda mengembalikan lebih dari satu nilai per baris, tetapkan bentuknya secara eksplisit. Ini menghindari kejutan dan kerusakan pada versi mendatang.

kembalikan list dan perluas menjadi kolom

Gunakan result_type='expand' untuk membagi list/array menjadi beberapa kolom.

def wins_losses(row):
    # Derive wins and losses as two outputs
    wins = row["Wins"]
    losses = row["Games"] - row["Wins"] if "Games" in row else np.nan
    return [wins, losses]

# Example using team_stats, which has "Wins" and "Games"
expanded = team_stats.apply(wins_losses, axis=1, result_type="expand")
expanded.columns = ["WinsOut", "LossesOut"]
team_stats = pd.concat([team_stats, expanded], axis=1)

kembalikan series atau dict untuk menamai kolom secara otomatis

Mengembalikan Series atau dict dari tiap baris menghasilkan DataFrame dengan label kolom yang sesuai.

def summary_row(row):
    return pd.Series(
        {
            "IsWinningSeason": row["Wins"] >= 90,
            "RunRatio": (row["RunsScored"] / row["RunsAllowed"]),
        }
    )

summary = team_stats.apply(summary_row, axis=1)
team_stats = pd.concat([team_stats, summary], axis=1)

Tips Kinerja yang Penting

Penerapan .apply(axis=1) per baris memang praktis namun lambat pada frame besar karena memanggil fungsi Python Anda sekali per baris. Pola berikut menghindari hambatan tersebut.

  • Utamakan operasi pandas/NumPy tervektorisasi dan metode bawaan seperti sum, mean, clip, where, astype, dan metode string/aksesornya.
  • Untuk operasi numerik per baris/kolom yang menerima array, berikan raw=True agar mendapatkan array NumPy dan mengurangi overhead pandas.
  • Untuk pekerjaan se-elemen pada satu kolom, gunakan Series.map() atau metode tervektorisasi alih-alih DataFrame.apply(axis=1).
  • Hindari memodifikasi baris/kolom yang diberikan di dalam fungsi Anda; kembalikan nilai baru sebagai gantinya.

Catatan Versi yang Perlu Anda Ketahui (pandas 2.x)

Rilis pandas terbaru memperketat perilaku terkait .apply() sehingga hasil lebih dapat diprediksi.

  • Keluaran mirip-list: Pada 2.0+, panjang list yang tidak konsisten memunculkan error. Gunakan panjang yang konsisten dan tetapkan result_type='expand' saat Anda menginginkan beberapa kolom.
  • Perluasan keluaran: Mengembalikan Series atau dict diperluas menjadi DataFrame dengan kunci-kunci tersebut sebagai kolom (stabil sejak 0,23).
  • Series.apply() berubah: Argumen convert_dtype sudah deprecated. Jika Anda membutuhkan tipe campuran, ubah dulu ke object (misalnya, s.astype("object").apply(fn)). Tanda tangan baru memungkinkan mengontrol apakah fn menerima skalar atau Series dalam lebih banyak konteks (misalnya, by_row).

.apply() vs. .map() vs. .applymap() vs. .agg()

Pilih API yang sesuai dengan bentuk transformasi Anda.

  • Series.map(func_or_dict): Transformasi se-elemen pada satu kolom. Terbaik untuk lookup atau fungsi sederhana.
  • DataFrame.apply(func, axis=1): Logika per baris yang membutuhkan beberapa kolom.
  • DataFrame.apply(func, axis=0): Logika per kolom (masukan berupa Series yang merepresentasikan kolom).
  • DataFrame.applymap(func): Se-elemen pada setiap sel. Gunakan seperlunya; metode tervektorisasi lebih cepat.
  • .agg()/.transform(): Agregasi dan transformasi per grup; utamakan ini dalam pipeline groupby.

Kesalahan Umum dan Perbaikan Cepat

Inilah isu yang paling sering menyebabkan hasil keliru atau perlambatan, beserta cara memperbaikinya.

  • Lupa axis=1 untuk logika per baris: Jika fungsi Anda tiba-tiba menerima kolom alih-alih baris, tambahkan axis=1.
  • Series tak terduga berisi list: Saat mengembalikan list/array dari tiap baris, tetapkan result_type='expand' untuk memecahnya menjadi kolom.
  • Kode per baris yang lambat: Ganti dengan ekspresi tervektorisasi atau metode bawaan; jika tidak memungkinkan, pertimbangkan raw=True untuk mengurangi overhead.
  • Memodifikasi baris masukan: Perlakukan masukan sebagai hanya-baca, dan kembalikan nilai baru.
  • Perubahan dtype: Jika fungsi Anda kadang mengembalikan non-integer, kolom integer dapat naik kasta menjadi float atau object. Lakukan cast setelahnya dengan astype jika diperlukan.

Kesimpulan

.apply() adalah alat yang fleksibel, namun bukan jalan pintas kinerja. Gunakan operasi tervektorisasi untuk aritmetika, agregasi, dan transformasi se-elemen pada satu kolom. Gunakan DataFrame.apply(axis=1) hanya ketika logika Anda benar-benar membutuhkan beberapa kolom per baris. Saat Anda menggunakannya, kendalikan bentuk keluaran dengan result_type, pertimbangkan raw=True untuk fungsi numerik, dan perhatikan dtypes. Pola ini menghasilkan hasil yang dapat diprediksi pada pandas modern dan lebih skalabel seiring pertumbuhan data Anda.

Topik
Python

Pelajari lebih lanjut tentang Python dan pandas

Kursus

Manipulasi Data dengan pandas

4 jam
568.2K
Pelajari cara mengimpor dan membersihkan data, menghitung statistik, serta membuat visualisasi dengan pandas.
Lihat DetailRight Arrow
Mulai Kursus
Lihat SelengkapnyaRight Arrow
Terkait

blogs

Tutorial Korelasi di R

Dapatkan pengenalan dasar-dasar korelasi di R: pelajari lebih lanjut tentang koefisien korelasi, matriks korelasi, plotting korelasi, dan sebagainya.
David Woods's photo

David Woods

13 mnt

blogs

Spaghetti Plot dan Jalur Badai

Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Hugo Bowne-Anderson's photo

Hugo Bowne-Anderson

13 mnt

blogs

12 Alternatif ChatGPT Terbaik yang Bisa Anda Coba pada 2026

Artikel ini menyajikan daftar alternatif ChatGPT yang akan meningkatkan produktivitas Anda.
Javier Canales Luna's photo

Javier Canales Luna

14 mnt

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Dario Radečić's photo

Dario Radečić

15 mnt

Lihat SelengkapnyaLihat Selengkapnya