Kecepatan pengolahan DataFrame lebih ditentukan oleh cara operasinya dinyatakan daripada oleh jumlah barisnya semata. Topik ini membandingkan vektorisasi, yakni pemrosesan seluruh array dalam satu operasi, dengan perulangan per baris pada seratus ribu bacaan sensor, kemudian melengkapinya dengan pola iterrows yang dihindari, metode query, dan dtype kategori sebagai pengurang kerja. Setelah membaca, pemilihan pola pengolahan dapat disesuaikan dengan ukuran data dan sifat perhitungan yang dihadapi.
Vektorisasi versus perulangan per baris#
Operasi tervektorisasi mengeksekusi satu pernyataan untuk seluruh array NumPy di tingkat C, sedangkan perulangan Python mengeksekusi satu pernyataan untuk setiap barisnya. Biaya interpreter Python pada setiap iterasi inilah yang membuat pola perulangan mahal, sedangkan versi tervektorisasi mengirim seluruh perhitungan sekaligus ke rutinitas yang dikompilasi. Blok berikut menguji keduanya pada konversi suhu Celsius ke Fahrenheit dengan rumus terhadap seratus ribu baris.
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
n = 96
df = pd.DataFrame({
"waktu": pd.date_range("2026-01-05 07:00", periods=n, freq="15min"),
"ruang": rng.choice(["Lab A", "Lab B", "Ruang Arsip"], n, p=[0.4, 0.35, 0.25]),
"suhu_c": np.round(rng.normal(24, 1.5, n), 1),
"lembap_pct": np.round(rng.normal(60, 5, n), 1),
"status_sensor": rng.choice(["normal", "kalibrasi", "rusak"], n, p=[0.85, 0.10, 0.05]),
})
df.to_csv("sensor_log.csv", index=False) # dataset bersama untuk seluruh modul
rng_besar = np.random.default_rng(42)
besar = pd.DataFrame({"suhu_c": np.round(rng_besar.normal(24, 1.5, 100_000), 1)})
arr = besar["suhu_c"].to_numpy()
vektor = arr * 1.8 + 32
per_baris = []
for nilai in arr:
per_baris.append(nilai * 1.8 + 32)
print("baris data:", len(besar))
print("hasil sama:", np.allclose(vektor, per_baris))baris data: 100000
hasil sama: TrueFungsi np.allclose membandingkan dua array dengan toleransi dan mengembalikan True, sehingga kedua pola terbukti menghasilkan nilai yang sama untuk seratus ribu baris. Waktu eksekusinya sengaja tidak dicetak karena nilainya berubah antar mesin, tetapi selisih polanya konsisten, yaitu versi per baris membutuhkan waktu berpuluhan kali lebih lama pada ukuran data ini. Perbedaan itu berasal dari biaya interpreter yang dibayar seratus ribu kali pada perulangan, dan hanya sekali pada operasi vektor. Konversi seluruh kolom seharusnya selalu ditulis dalam bentuk operasi array seperti ini.
Menghindari iterrows#
Metode iterrows menghasilkan satu Series untuk setiap baris sehingga menjadi pola perulangan yang paling mahal, dan pola ini dihindari ketika perhitungannya dapat divetorisasi. Selain biaya interpreter per baris, setiap iterasinya masih membangun objek Series baru yang lebih mahal daripada sekadar membaca elemen array. Blok berikut dibiarkan tidak dijalankan karena perulangan seratus ribu barisnya memakan waktu berpuluhan detik pada sandbox ini.
# tidak-dijalankan
import numpy as np
import pandas as pd
besar = pd.DataFrame(
{"suhu_c": np.round(np.random.default_rng(42).normal(24, 1.5, 100_000), 1)}
)
hasil = []
for indeks, baris in besar.iterrows():
hasil.append(baris["suhu_c"] * 1.8 + 32)Perulangan tetap menjadi pilihan yang sah untuk pekerjaan yang memang tidak dapat divetorisasi, misalnya panggilan jaringan atau operasi berkas yang harus dilakukan per baris. Untuk perhitungan angka seperti konversi satuan pada blok sebelumnya, tidak ada alasan memilih pola ini. Kebiasaan yang sehat adalah menulis versi vektorisnya lebih dahulu, lalu mempertimbangkan perulangan hanya setelah kasus tak tervektorisasi ditemukan.
Query untuk penyaringan ekspresif#
Metode query menyaring baris dengan satu ekspresi teks, sehingga kondisi majemuk tidak lagi ditulis sebagai rangkaian mask yang bertumpuk. Ekspresinya ditulis sebagaimana kalimatnya dibaca, dengan and dan or sebagai penghubungnya, dan hasilnya setara dengan gabungan mask boolean pada topik Indeks Boolean. Blok berikut menyaring bacaan Lab A yang melebihi 25 derajat dari dataset kontrak.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
panas = df.query("suhu_c > 25 and ruang == 'Lab A'", engine="python")
print(panas[["waktu", "ruang", "suhu_c"]].head(3))
print("jumlah baris:", len(panas)) waktu ruang suhu_c
32 2026-01-05 15:00:00 Lab A 26.2
43 2026-01-05 17:45:00 Lab A 25.3
68 2026-01-06 00:00:00 Lab A 27.2
jumlah baris: 4Empat baris memenuhi kedua syaratnya, dan tiga pertamanya terlihat pada keluaran. Parameter engine="python" memaksa evaluasi dengan Python murni, sehingga keluaran blok tidak bergantung pada versi pustaka numexpr yang kebetulan terpasang, sebagaimana catatan perilaku query pada topik Penyaringan dengan query. Pada lingkungan yang numexprnya didukung, evaluasi ekspresi dapat dipercepat tanpa mengubah bentuk kodenya. Keringkasan ekspresi inilah yang membuat query menjadi alat pengurang kerja, bukan sekadar gaya penulisan alternatif.
Dtype kategori untuk memori dan kecepatan#
Kolom bertipe kategori menyimpan setiap nilai unik sekali di samping kode angka per barisnya, sehingga kolom teks dengan nilai berulang menjadi ringan sekaligus cepat dikelompokkan. Perilaku dasarnya sudah dibahas pada topik Dtype Kategori, sedangkan di sini fokusnya adalah dampak memori dan performanya. Blok berikut mengubah kolom ruang dataset kontrak menjadi kategori dan membandingkan penggunaan memorinya.
import pandas as pd
df = pd.read_csv("sensor_log.csv", parse_dates=["waktu"])
memori_str = df["ruang"].memory_usage(deep=True)
df["ruang"] = df["ruang"].astype("category")
print("dtype:", df["ruang"].dtype)
print("kategori:", list(df["ruang"].cat.categories))
print("memori str (byte):", memori_str)
print("memori kategori (byte):", df["ruang"].memory_usage(deep=True))dtype: category
kategori: ['Lab A', 'Lab B', 'Ruang Arsip']
memori str (byte): 1512
memori kategori (byte): 274Penggunaan memori kolom turun dari 1512 byte menjadi 274 byte hanya karena tiga nilai uniknya kini disimpan sekali, sedangkan 96 barisnya tinggal menyimpan kode angka. Penghematan ini membesar seiring jumlah baris, karena ukuran kode angkanya tetap sedangkan representasi teks tumbuh mengikuti panjang datanya. Operasi pengelompokan dan perbandingan juga bekerja pada kode angka, sehingga groupby atas kolom kategori menghabiskan lebih sedikit kerja daripada atas teks. Konversi ke kategori layak dilakukan setiap kali jumlah nilai unik jauh lebih kecil daripada jumlah barisnya.
Kesalahan umum#
Kesimpulan performa yang diambil dari data yang terlalu kecil sering terbalik, karena biaya tetap setiap panggilan fungsi menyamarkan selisih antar pola. Pada dataset kontrak yang hanya berisi 96 baris, versi tervektorisasi dapat berakhir sama cepat atau bahkan lebih lambat daripada perulangan Python, sebagian waktunya habis untuk menyiapkan array, memeriksa tipe, dan mengalokasikan keluaran. Selisih pola baru terlihat setelah biaya tetap itu terserap oleh banyaknya baris, sebagaimana seratus ribu baris pada blok pertama topik ini. Kesimpulan yang diambil dari ukuran kecil kemudian salah arah ketika diterapkan pada data produksi yang jauh lebih besar.
Perbaikannya adalah mengukur pada data berukuran realistis terlebih dahulu, misalnya seratus ribu baris, sebelum menetapkan pola mana yang dipakai. Tetapkan besaran yang diukur sebelum menjalankan pengukuran, lalu ulangi pengukurannya beberapa kali karena waktu eksekusi berfluktuasi antar eksekusi. Di sisi lain, penghematan milidetik tidak boleh mengalahkan keterbacaan untuk skrip yang berjalan sekali jalan, karena waktu pembaca ulang kode juga berharga. Pemilihan pola dengan demikian menimbang ukuran data, frekuensi eksekusi, dan kejelasan kodenya sekaligus.
Ringkasan#
- Operasi tervektorisasi seperti
df["suhu_c"].to_numpy() * 1.8 + 32menghasilkan keluaran yang sama dengan perulangan per baris, dengan biaya yang jauh lebih kecil pada data besar. iterrowsmembangun satuSeriesuntuk setiap baris dan dihindari selama perhitungannya dapat divetorisasi.query("suhu_c > 25 and ruang == 'Lab A'")meringkas kondisi majemuk menjadi satu ekspresi, dan dtype kategori menyimpan nilai unik sekali sehingga memori serta pengelompokannya lebih ringan.- Kesimpulan performa diuji pada data berukuran realistis, bukan pada puluhan baris.
Referensi#
- Enhancing performance — pandas User Guide — panduan resmi vektorisasi dan penghindaran perulangan baris pada pandas.
- Categorical data — pandas User Guide — dokumentasi resmi dtype kategori beserta penghematan memorinya.