Bagaimana cara memilih baris dari DataFrame
berdasarkan pada beberapa kolom di Python Pandas?
Dalam SQL, saya akan menggunakan:
SELECT *
FROM table
WHERE colume_name = some_value
Saya mencoba melihat dokumentasi panda tetapi tidak segera menemukan jawabannya.
Jawaban:
Untuk memilih baris yang nilai kolomnya sama dengan skalar
some_value
,, gunakan==
:Untuk memilih baris yang nilai kolomnya dapat diubah
some_values
, gunakanisin
:Gabungkan beberapa kondisi dengan
&
:Perhatikan tanda kurung. Karena aturan prioritas operator Python ,
&
mengikat lebih erat dari<=
dan>=
. Jadi, tanda kurung dalam contoh terakhir diperlukan. Tanpa tanda kurungdiuraikan sebagai
yang menghasilkan nilai Kebenaran dari suatu Seri adalah kesalahan yang mendua .
Untuk memilih baris yang nilai kolomnya tidak sama
some_value
, gunakan!=
:isin
mengembalikan Seri boolean, jadi untuk memilih baris yang nilainya tidak dalamsome_values
, negasikan Seri boolean menggunakan~
:Sebagai contoh,
hasil panen
Jika Anda memiliki beberapa nilai yang ingin Anda sertakan, masukkan ke dalam daftar (atau lebih umum, setiap iterable) dan gunakan
isin
:hasil panen
Perhatikan, bagaimanapun, bahwa jika Anda ingin melakukan ini berkali-kali, itu lebih efisien untuk membuat indeks terlebih dahulu, dan kemudian gunakan
df.loc
:hasil panen
atau, untuk memasukkan beberapa nilai dari penggunaan indeks
df.index.isin
:hasil panen
sumber
df.where(condition)
, kondisinya harus memiliki bentuk yang samadf
.df[df['column_name'] == some_value]
berhasil, mengapa kita perlu menambahkan di.loc
sini?Ada beberapa cara untuk memilih baris dari bingkai data panda:
df[df['col'] == value
])df.iloc[...]
)df.xs(...)
)df.query(...)
APIDi bawah ini saya tunjukkan contoh masing-masing, dengan saran kapan harus menggunakan teknik tertentu. Asumsikan kriteria kami adalah kolom
'A'
=='foo'
(Catatan tentang kinerja: Untuk setiap jenis basis, kita dapat menjaga hal-hal sederhana dengan menggunakan API panda atau kita dapat menjelajah di luar API, biasanya ke dalam
numpy
, dan mempercepatnya.)Pengaturan
Hal pertama yang kita perlukan adalah mengidentifikasi suatu kondisi yang akan bertindak sebagai kriteria kita untuk memilih baris. Kami akan mulai dengan kasus OP
column_name == some_value
, dan menyertakan beberapa kasus penggunaan umum lainnya.Meminjam dari @unutbu:
1. Pengindeksan Boolean
... Pengindeksan boolean membutuhkan menemukan nilai sebenarnya dari setiap
'A'
kolom baris yang sama'foo'
, kemudian menggunakan nilai-nilai kebenaran untuk mengidentifikasi baris mana yang harus dipertahankan. Biasanya, kami akan menamai seri ini, array nilai kebenaranmask
,. Kami akan melakukannya di sini juga.Kami kemudian dapat menggunakan topeng ini untuk mengiris atau mengindeks bingkai data
Ini adalah salah satu cara paling sederhana untuk menyelesaikan tugas ini dan jika kinerja atau intuitifitas tidak menjadi masalah, ini harus menjadi metode yang Anda pilih. Namun, jika kinerja merupakan masalah, maka Anda mungkin ingin mempertimbangkan cara alternatif untuk membuatnya
mask
.2. Pengindeksan posisi
Pengindeksan posisi (
df.iloc[...]
) memiliki kasus penggunaannya, tetapi ini bukan salah satunya. Untuk mengidentifikasi di mana harus mengiris, pertama-tama kita perlu melakukan analisis boolean yang sama seperti yang kita lakukan di atas. Ini membuat kami melakukan satu langkah ekstra untuk menyelesaikan tugas yang sama.3. Pengindeksan label
Pengindeksan label bisa sangat berguna, tetapi dalam hal ini, kami kembali melakukan lebih banyak pekerjaan tanpa manfaat
4.
df.query()
APIpd.DataFrame.query
adalah cara yang sangat elegan / intuitif untuk melakukan tugas ini, tetapi seringkali lebih lambat. Namun , jika Anda memperhatikan timing di bawah ini, untuk data besar, kueri ini sangat efisien. Lebih dari pendekatan standar dan besarnya serupa sebagai saran terbaik saya.Preferensi saya adalah menggunakan
Boolean
mask
Perbaikan yang sebenarnya dapat dilakukan dengan memodifikasi cara kami membuat
Boolean
mask
.mask
alternatif 1Gunakan
numpy
array yang mendasari dan lupakan overhead untuk membuat yang lainpd.Series
Saya akan menunjukkan tes waktu yang lebih lengkap di bagian akhir, tetapi lihat saja peningkatan kinerja yang kami dapatkan menggunakan kerangka data sampel. Pertama, kita melihat perbedaan dalam menciptakan
mask
Mengevaluasi
mask
dengannumpy
array adalah ~ 30 kali lebih cepat. Ini sebagian karenanumpy
evaluasi sering lebih cepat. Ini juga sebagian karena kurangnya overhead yang diperlukan untuk membangun indeks danpd.Series
objek yang sesuai .Selanjutnya, kita akan melihat waktu untuk mengiris dengan yang satu
mask
versus yang lain.Keuntungan kinerja tidak diucapkan. Kita akan melihat apakah ini tahan terhadap pengujian yang lebih kuat.
mask
alternatif 2Kita bisa merekonstruksi bingkai data juga. Ada peringatan besar ketika merekonstruksi kerangka data — Anda harus berhati-hati
dtypes
ketika melakukannya!Alih-alih
df[mask]
kita akan melakukan iniJika bingkai data adalah tipe campuran, yang merupakan contoh kita, maka ketika kita mendapatkan
df.values
array yang dihasilkan adalahdtype
object
dan akibatnya, semua kolom dari bingkai data baru akan menjadidtype
object
. Dengan demikian membutuhkanastype(df.dtypes)
dan membunuh keuntungan kinerja potensial.Namun, jika frame data bukan tipe campuran, ini adalah cara yang sangat berguna untuk melakukannya.
Diberikan
Melawan
Kami memotong waktu menjadi dua.
mask
alternatif 3@unutbu juga menunjukkan kepada kita cara menggunakan
pd.Series.isin
untuk memperhitungkan setiap elemendf['A']
dalam serangkaian nilai. Ini mengevaluasi ke hal yang sama jika set nilai kami adalah satu set nilai, yaitu'foo'
. Tetapi juga menggeneralisasi untuk memasukkan set nilai yang lebih besar jika diperlukan. Ternyata, ini masih cukup cepat walaupun itu adalah solusi yang lebih umum. Satu-satunya kerugian nyata adalah pada intuisi bagi mereka yang tidak terbiasa dengan konsep tersebut.Namun, seperti sebelumnya, kita dapat memanfaatkan
numpy
untuk meningkatkan kinerja tanpa mengorbankan apa pun. Kami akan gunakannp.in1d
Waktu
saya akan menyertakan konsep lain yang disebutkan dalam posting lain juga untuk referensi.
Kode di bawah ini
Setiap kolom dalam tabel ini mewakili kerangka data panjang yang berbeda di mana kami menguji setiap fungsi. Setiap kolom menunjukkan waktu relatif yang diambil, dengan fungsi tercepat diberi indeks dasar
1.0
.Anda akan melihat bahwa waktu tercepat tampaknya dibagi antara
mask_with_values
danmask_with_in1d
Fungsi
Pengujian
Penentuan Waktu Khusus
Melihat kasus khusus ketika kami memiliki satu non-objek
dtype
untuk seluruh bingkai data. Kode di bawah iniTernyata, rekonstruksi tidak layak melewati beberapa ratus baris.
Fungsi
Pengujian
sumber
.iloc(numpy.where(..))
membandingkan dalam skema ini? ii) apakah Anda berharap peringkatnya sama ketika menggunakan beberapa kondisi?pd.Series.isin
, catatan itu tidak digunakannp.in1d
di bawah tenda dalam skenario tertentu, penggunaan Khash pada orang lain, dan secara implisit menerapkan trade-off antara biaya hashing terhadap kinerja dalam situasi tertentu. Jawaban ini lebih detail.[{P|EXP}TIME]
- dan[{C|P|EXP}SPACE]
- biaya penggunaan bentuk-bentuk blok-sintaks yang diusulkan di atas (memproses top-down seluruh dataframe sekaligus) tumbuh , yaitu ketika diskalakan ke beberapa~1E6, ~1E9, ~1E12
jumlah baris? Terima kasih telah menunjukkan kepada kami seluruh gambar, Pak. Bacaan patokan kuantitatif dengan[min, Avg, MAX, StDev]
selalu diterima, karena baikmin
danMAX
nilai - nilai menyertaiMean/StDev
relief batch.tl; dr
Panda setara dengan
adalah
Beberapa kondisi:
atau
Contoh kode
Dalam kode di atas itu adalah baris
df[df.foo == 222]
yang memberikan baris berdasarkan nilai kolom,222
dalam hal ini.Berbagai kondisi juga dimungkinkan:
Tetapi pada saat itu saya akan merekomendasikan menggunakan fungsi kueri , karena kurang verbose dan menghasilkan hasil yang sama:
sumber
query
adalah satu-satunya jawaban di sini yang kompatibel dengan metode chaining. Sepertinya itu analog panda kefilter
dalam dplyr.[
tidak bulat tanda kurung(
di luar.|
itu untuk DAN, tapi tentu saja itu OR-operator ...df[condition1][condition2]
df.query('`my col` == 124')
Saya menemukan sintaks dari jawaban sebelumnya menjadi redundan dan sulit diingat. Panda memperkenalkan
query()
metode ini di v0.13 dan saya lebih menyukainya. Untuk pertanyaan Anda, Anda bisa melakukannyadf.query('col == val')
Direproduksi dari http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query
Anda juga dapat mengakses variabel di lingkungan dengan menambahkan sebuah
@
.sumber
numexpr
menginstal paket .Fleksibilitas menggunakan
.query
denganpandas >= 0.25.0
:Agustus 2019 jawaban diperbarui
Karena
pandas >= 0.25.0
kita dapat menggunakanquery
metode untuk memfilter dataframe dengan metode panda dan bahkan nama kolom yang memiliki spasi. Biasanya spasi dalam nama kolom akan memberikan kesalahan, tetapi sekarang kita dapat menyelesaikannya dengan menggunakan backtick (`) lihat GitHub :Menggunakan
.query
dengan metodestr.endswith
:Keluaran
Kami juga dapat menggunakan variabel lokal dengan mengawali dengan
@
dalam permintaan kami:Keluaran
sumber
Hasil lebih cepat bisa dicapai menggunakan numpy.where .
Misalnya, dengan pengaturan unubtu -
Perbandingan waktu:
sumber
Ini adalah contoh sederhana
sumber
Untuk memilih hanya kolom tertentu dari beberapa kolom untuk nilai yang diberikan dalam panda:
Pilihan:
atau
sumber
Untuk menambahkan pertanyaan terkenal ini (meskipun agak terlambat): Anda juga dapat melakukan
df.groupby('column_name').get_group('column_desired_value').reset_index()
untuk membuat bingkai data baru dengan kolom yang ditentukan memiliki nilai tertentu. MisalnyaJalankan ini memberi:
sumber
get_group()
akan secara otomatis mengembalikan dataframe. Anda juga bisa mengatakan "drop = True" sebagai parameterreset_index()
. Dengan kata lain, dapat disingkat menjadi:b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Anda juga dapat menggunakan .apply:
Ini benar-benar berfungsi baris-bijaksana (yaitu, menerapkan fungsi ke setiap baris).
Outputnya adalah
Hasilnya sama dengan menggunakan seperti yang disebutkan oleh @unutbu
sumber