Python Pandas: Dapatkan indeks baris yang cocok dengan nilai kolom tertentu

277

Diberikan DataFrame dengan kolom "BoolCol", kami ingin menemukan indeks DataFrame di mana nilai untuk "BoolCol" == Benar

Saat ini saya memiliki cara iterasi untuk melakukannya, yang bekerja dengan sempurna:

for i in range(100,3000):
    if df.iloc[i]['BoolCol']== True:
         print i,df.iloc[i]['BoolCol']

Tapi ini bukan cara panda yang tepat untuk melakukannya. Setelah beberapa penelitian, saya saat ini menggunakan kode ini:

df[df['BoolCol'] == True].index.tolist()

Yang ini memberi saya daftar indeks, tetapi tidak cocok, ketika saya memeriksanya dengan melakukan:

df.iloc[i]['BoolCol']

Hasilnya sebenarnya Salah !!

Mana yang merupakan cara Panda yang benar untuk melakukan ini?

Saya ingin lencana
sumber

Jawaban:

429

df.iloc[i]mengembalikan ithderetan df. itidak mengacu pada label indeks, iadalah indeks berbasis 0.

Sebaliknya, atribut indexmengembalikan label indeks yang sebenarnya , bukan indeks baris numerik:

df.index[df['BoolCol'] == True].tolist()

atau yang setara,

df.index[df['BoolCol']].tolist()

Anda dapat melihat perbedaannya cukup jelas dengan bermain dengan DataFrame dengan indeks non-default yang tidak sama dengan posisi numerik baris:

df = pd.DataFrame({'BoolCol': [True, False, False, True, True]},
       index=[10,20,30,40,50])

In [53]: df
Out[53]: 
   BoolCol
10    True
20   False
30   False
40    True
50    True

[5 rows x 1 columns]

In [54]: df.index[df['BoolCol']].tolist()
Out[54]: [10, 40, 50]

Jika Anda ingin menggunakan indeks ,

In [56]: idx = df.index[df['BoolCol']]

In [57]: idx
Out[57]: Int64Index([10, 40, 50], dtype='int64')

maka Anda dapat memilih baris menggunakan locbukaniloc :

In [58]: df.loc[idx]
Out[58]: 
   BoolCol
10    True
40    True
50    True

[3 rows x 1 columns]

Catatan yang locjuga dapat menerima array boolean :

In [55]: df.loc[df['BoolCol']]
Out[55]: 
   BoolCol
10    True
40    True
50    True

[3 rows x 1 columns]

Jika Anda memiliki larik boolean mask,, dan memerlukan nilai indeks ordinal, Anda dapat menghitungnya menggunakannp.flatnonzero :

In [110]: np.flatnonzero(df['BoolCol'])
Out[112]: array([0, 3, 4])

Gunakan df.ilocuntuk memilih baris berdasarkan indeks ordinal:

In [113]: df.iloc[np.flatnonzero(df['BoolCol'])]
Out[113]: 
   BoolCol
10    True
40    True
50    True
unutbu
sumber
9
Namun cara lain adalah melakukan df.query('BoolCol').
Phillip Cloud
3
Saya tahu ini sudah lama, tapi saya ingin tahu apakah ada cara mudah untuk mendapatkan nomor indeks berbasis 0 dari kueri. Saya memerlukan nomor iloc karena saya ingin memilih beberapa baris sebelum dan sesudah baris memenuhi kondisi tertentu. Jadi rencana saya adalah mendapatkan 0-indeks baris yang memenuhi syarat dan kemudian membuat irisan untuk digunakan di iloc (). Satu-satunya hal yang saya lihat adalah get_loc, tetapi tidak bisa mengambil array.
sheridp
3
@sheridp: Jika Anda memiliki topeng boolean, Anda dapat menemukan indeks ordinal mana maskadalah Truedengan menggunakan np.flatnonzero. Saya telah mengedit posting di atas untuk menunjukkan apa yang saya maksud.
unutbu
8
Saran Anda indices = np.flatnonzero(df[col_name] == category_name)membuat saya tahu persis apa yang ditanyakan oleh judul pertanyaan itu, yang secara mengejutkan sulit ditemukan di Internet.
ClimbsRocks
Jika Anda hanya ingin kembali indeks, berapa overhead df [dftest] .index? Apakah ini membuat bingkai data perantara (yang datanya mungkin gibabytes). Bagaimana dengan dftest? Bukankah ini juga mengalokasikan objek menengah yang sangat besar di mana indeks yang dikembalikan mungkin sangat kecil, atau bahkan kosong. Apakah ini dioptimalkan secara ajaib dengan menggunakan pandangan malas. Jika tidak maka pasti harus ada cara yang efisien.
user48956
31

Dapat dilakukan menggunakan fungsi numpy where ():

import pandas as pd
import numpy as np

In [716]: df = pd.DataFrame({"gene_name": ['SLC45A1', 'NECAP2', 'CLIC4', 'ADC', 'AGBL4'] , "BoolCol": [False, True, False, True, True] },
       index=list("abcde"))

In [717]: df
Out[717]: 
  BoolCol gene_name
a   False   SLC45A1
b    True    NECAP2
c   False     CLIC4
d    True       ADC
e    True     AGBL4

In [718]: np.where(df["BoolCol"] == True)
Out[718]: (array([1, 3, 4]),)

In [719]: select_indices = list(np.where(df["BoolCol"] == True)[0])

In [720]: df.iloc[select_indices]
Out[720]: 
  BoolCol gene_name
b    True    NECAP2
d    True       ADC
e    True     AGBL4

Meskipun Anda tidak selalu membutuhkan indeks untuk pertandingan, tetapi memetikan jika Anda membutuhkan:

In [796]: df.iloc[select_indices].index
Out[796]: Index([u'b', u'd', u'e'], dtype='object')

In [797]: df.iloc[select_indices].index.tolist()
Out[797]: ['b', 'd', 'e']
Surya
sumber
2

Cara sederhana adalah mengatur ulang indeks DataFrame sebelum memfilter:

df_reset = df.reset_index()
df_reset[df_reset['BoolCol']].index.tolist()

Agak macet, tapi cepat!

Ben Druitt
sumber
1

Pertama, Anda dapat memeriksa querykapan kolom target diketik bool (PS: tentang cara menggunakannya, silakan periksa tautan )

df.query('BoolCol')
Out[123]: 
    BoolCol
10     True
40     True
50     True

Setelah kita menyaring df asli dengan kolom Boolean kita dapat memilih indeks.

df=df.query('BoolCol')
df.index
Out[125]: Int64Index([10, 40, 50], dtype='int64')

Juga panda memiliki nonzero, kita hanya memilih posisi dari Truebaris dan menggunakannya iris DataFrameatauindex

df.index[df.BoolCol.nonzero()[0]]
Out[128]: Int64Index([10, 40, 50], dtype='int64')
YOBEN_S
sumber
1

Jika Anda ingin menggunakan objek dataframe hanya sekali, gunakan:

df['BoolCol'].loc[lambda x: x==True].index
mbh86
sumber
0

Saya memperpanjang pertanyaan ini yaitu bagaimana cara mendapatkan nilai row, columndan valuedari semua nilai kecocokan?

ini solusinya:

import pandas as pd
import numpy as np


def search_coordinate(df_data: pd.DataFrame, search_set: set) -> list:
    nda_values = df_data.values
    tuple_index = np.where(np.isin(nda_values, [e for e in search_set]))
    return [(row, col, nda_values[row][col]) for row, col in zip(tuple_index[0], tuple_index[1])]


if __name__ == '__main__':
    test_datas = [['cat', 'dog', ''],
                  ['goldfish', '', 'kitten'],
                  ['Puppy', 'hamster', 'mouse']
                  ]
    df_data = pd.DataFrame(test_datas)
    print(df_data)
    result_list = search_coordinate(df_data, {'dog', 'Puppy'})
    print(f"\n\n{'row':<4} {'col':<4} {'name':>10}")
    [print(f"{row:<4} {col:<4} {name:>10}") for row, col, name in result_list]

Keluaran:

          0        1       2
0       cat      dog        
1  goldfish           kitten
2     Puppy  hamster   mouse


row  col        name
0    1           dog
2    0         Puppy
Carson
sumber