Bagaimana cara mengulangi baris dalam DataFrame di Pandas?
Jawab: JANGAN * !
Iterasi dalam panda adalah anti-pola, dan merupakan sesuatu yang harus Anda lakukan hanya jika Anda telah kehabisan setiap opsi lainnya. Anda tidak boleh menggunakan fungsi apa pun dengan " iter
" namanya lebih dari beberapa ribu baris atau Anda harus terbiasa dengan banyak menunggu.
Apakah Anda ingin mencetak DataFrame? Gunakan DataFrame.to_string()
.
Apakah Anda ingin menghitung sesuatu? Dalam hal ini, cari metode dalam urutan ini (daftar dimodifikasi dari sini ):
- Vektorisasi
- Rutinitas cython
- Daftar Pemahaman (vanilla
for
loop)
DataFrame.apply()
: i) Pengurangan yang dapat dilakukan dalam cython, ii) Iterasi dalam ruang python
DataFrame.itertuples()
dan iteritems()
DataFrame.iterrows()
iterrows
dan itertuples
(keduanya menerima banyak suara sebagai jawaban atas pertanyaan ini) harus digunakan dalam keadaan yang sangat jarang, seperti menghasilkan objek baris / nametuple untuk pemrosesan sekuensial, yang merupakan satu-satunya hal yang berguna untuk fungsi-fungsi ini.
Banding ke Otoritas
Halaman dokumen tentang pengulangan memiliki kotak peringatan merah besar yang bertuliskan:
Iterasi melalui objek panda umumnya lambat. Dalam banyak kasus, iterasi secara manual di atas baris tidak diperlukan [...].
* Ini sebenarnya sedikit lebih rumit daripada "jangan". df.iterrows()
adalah jawaban yang benar untuk pertanyaan ini, tetapi "vectorize your ops" adalah yang lebih baik. Saya akan mengakui bahwa ada keadaan di mana iterasi tidak dapat dihindari (misalnya, beberapa operasi di mana hasilnya tergantung pada nilai yang dihitung untuk baris sebelumnya). Namun, perlu beberapa keakraban dengan perpustakaan untuk mengetahui kapan. Jika Anda tidak yakin apakah Anda membutuhkan solusi berulang, Anda mungkin tidak. PS: Untuk mengetahui lebih banyak tentang pemikiran saya untuk menulis jawaban ini, lompat ke bagian paling bawah.
Sejumlah operasi dasar dan komputasi yang baik "di-vektor-kan" oleh panda (baik melalui NumPy, atau melalui fungsi-fungsi Cythonized). Ini termasuk aritmatika, perbandingan, pengurangan (sebagian besar), pembentukan kembali (seperti berputar), bergabung, dan operasi grup oleh. Lihat dokumentasi tentang Fungsi Dasar Esensial untuk menemukan metode vektorised yang cocok untuk masalah Anda.
Jika tidak ada, jangan ragu untuk menulis sendiri menggunakan ekstensi cython khusus .
Pemahaman daftar harus menjadi porta panggilan Anda berikutnya jika 1) tidak ada solusi vektorisasi yang tersedia, 2) kinerja penting, tetapi tidak cukup penting untuk melewati kerumitan cythonisasi kode Anda, dan 3) Anda mencoba melakukan transformasi elementwise pada kode Anda. Ada sejumlah bukti yang baik untuk menunjukkan bahwa pemahaman daftar cukup cepat (dan bahkan terkadang lebih cepat) untuk banyak tugas panda umum.
Rumusnya sederhana,
# iterating over one column - `f` is some function that processes your data
result = [f(x) for x in df['col']]
# iterating over two columns, use `zip`
result = [f(x, y) for x, y in zip(df['col1'], df['col2'])]
# iterating over multiple columns - same data type
result = [f(row[0], ..., row[n]) for row in df[['col1', ...,'coln']].to_numpy()]
# iterating over multiple columns - differing data type
result = [f(row[0], ..., row[n]) for row in zip(df['col1'], ..., df['coln'])]
Jika Anda bisa merangkum logika bisnis Anda ke dalam suatu fungsi, Anda bisa menggunakan pemahaman daftar yang menyebutnya. Anda dapat membuat hal-hal rumit yang semena-mena bekerja melalui kesederhanaan dan kecepatan python mentah.
Pemahaman Caveats List menganggap bahwa data Anda mudah dikerjakan - artinya adalah tipe data Anda konsisten dan Anda tidak memiliki NaN, tetapi ini tidak selalu dapat dijamin.
- Yang pertama lebih jelas, tetapi ketika berhadapan dengan NaN, lebih memilih metode panda built-in jika ada (karena mereka memiliki logika penanganan kasus sudut jauh lebih baik), atau memastikan logika bisnis Anda menyertakan logika penanganan NaN yang sesuai.
- Saat berurusan dengan tipe data campuran, Anda harus mengulanginya alih-
zip(df['A'], df['B'], ...)
alih df[['A', 'B']].to_numpy()
karena yang terakhir secara implisit mengirimkan data ke tipe yang paling umum. Sebagai contoh jika A adalah numerik dan B adalah string, to_numpy()
akan melemparkan seluruh array ke string, yang mungkin bukan yang Anda inginkan. Untungnya zip
ping kolom Anda bersama adalah solusi paling mudah untuk ini.
* YMMV untuk alasan yang diuraikan di bagian Peringatan di atas.
Contoh yang Jelas
Mari kita tunjukkan perbedaannya dengan contoh sederhana menambahkan dua kolom panda A + B
. Ini adalah operasi vektorizable, sehingga akan mudah untuk membandingkan kinerja metode yang dibahas di atas.
Kode benchmark, untuk referensi Anda.
Saya harus menyebutkan, bahwa tidak selalu luka dan kering seperti ini. Terkadang jawaban untuk "apa metode terbaik untuk operasi" adalah "itu tergantung pada data Anda". Saran saya adalah untuk menguji berbagai pendekatan pada data Anda sebelum memutuskannya.
Bacaan lebih lanjut
* Metode string panda adalah "vektor" dalam arti bahwa mereka ditentukan pada seri tetapi beroperasi pada setiap elemen. Mekanisme yang mendasarinya masih berulang, karena operasi string secara inheren sulit untuk di-vektorisasi.
Mengapa Saya Menulis Jawaban ini
Tren umum yang saya perhatikan dari pengguna baru adalah untuk mengajukan pertanyaan dari formulir "bagaimana saya bisa beralih ke df saya untuk melakukan X?". Menampilkan kode yang memanggil iterrows()
saat melakukan sesuatu di dalam for loop. Inilah sebabnya. Seorang pengguna baru ke perpustakaan yang belum diperkenalkan dengan konsep vektorisasi kemungkinan akan membayangkan kode yang memecahkan masalah mereka saat iterasi data mereka untuk melakukan sesuatu. Tidak tahu bagaimana cara mengulang melalui DataFrame, hal pertama yang mereka lakukan adalah Google dan berakhir di sini, pada pertanyaan ini. Mereka kemudian melihat jawaban yang diterima memberitahu mereka bagaimana caranya, dan mereka menutup mata mereka dan menjalankan kode ini tanpa terlebih dahulu mempertanyakan apakah iterasi bukan hal yang benar untuk dilakukan.
Tujuan dari jawaban ini adalah untuk membantu pengguna baru memahami bahwa iterasi tidak selalu merupakan solusi untuk setiap masalah, dan bahwa solusi yang lebih baik, lebih cepat, dan lebih idiomatik dapat ada, dan bahwa ada baiknya menginvestasikan waktu untuk menjelajahi mereka. Saya tidak mencoba untuk memulai perang iterasi vs vektorisasi, tapi saya ingin pengguna baru diberi tahu ketika mengembangkan solusi untuk masalah mereka dengan perpustakaan ini.