Python Pandas: Nhận chỉ mục của các hàng mà cột khớp với giá trị nhất định


274

Đưa ra một DataFrame có cột "BoolCol", chúng tôi muốn tìm các chỉ mục của DataFrame trong đó các giá trị cho "BoolCol" == True

Tôi hiện đang có cách lặp để làm điều đó, hoạt động hoàn hảo:

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

Nhưng đây không phải là cách chính xác của gấu trúc để làm điều đó. Sau một số nghiên cứu, tôi hiện đang sử dụng mã này:

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

Cái này cho tôi một danh sách các chỉ mục, nhưng chúng không khớp, khi tôi kiểm tra chúng bằng cách thực hiện:

df.iloc[i]['BoolCol']

Kết quả là sai !!

Đó sẽ là cách chính xác của Pandas để làm điều này?

Câu trả lời:


424

df.iloc[i]trả về ithhàng của df. ikhông đề cập đến nhãn chỉ mục, ilà chỉ mục dựa trên 0.

Ngược lại, thuộc tính indextrả về nhãn chỉ mục thực tế , không phải là chỉ số hàng số:

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

hoặc tương đương,

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

Bạn có thể thấy sự khác biệt khá rõ ràng bằng cách chơi với DataFrame với chỉ mục không mặc định không bằng vị trí số của hàng:

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]

Nếu bạn muốn sử dụng chỉ mục ,

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

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

sau đó bạn có thể chọn các hàng bằng cách sử dụng locthay vìiloc :

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

[3 rows x 1 columns]

Lưu ý rằng loccũng có thể chấp nhận mảng boolean :

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

[3 rows x 1 columns]

Nếu bạn có một mảng boolean maskvà cần các giá trị chỉ mục thứ tự, bạn có thể tính toán chúng bằng cách sử dụngnp.flatnonzero :

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

Sử dụng df.ilocđể chọn hàng theo chỉ số thứ tự:

In [113]: df.iloc[np.flatnonzero(df['BoolCol'])]
Out[113]: 
   BoolCol
10    True
40    True
50    True

9
Tuy nhiên, một cách khác là làm df.query('BoolCol').
Đám mây Phillip

3
Tôi biết điều này đã cũ, nhưng tôi tự hỏi liệu có một cách dễ dàng để có được các số chỉ mục dựa trên 0 từ một truy vấn. Tôi cần các số iloc vì tôi muốn chọn một số hàng trước và sau khi một hàng đáp ứng một điều kiện nhất định. Vì vậy, kế hoạch của tôi là lấy các chỉ số 0 của các hàng đáp ứng điều kiện và sau đó tạo các lát để sử dụng trong iloc (). Điều duy nhất tôi thấy là get_loc, nhưng nó không thể lấy một mảng.
sheridp

3
@sheridp: Nếu bạn có một chiếc mặt nạ boolean, bạn có thể tìm thấy các chỉ số thứ tự mà maskTruebằng cách sử dụng np.flatnonzero. Tôi đã chỉnh sửa bài viết ở trên để hiển thị những gì tôi muốn nói.
unutbu

8
Gợi ý của bạn cho indices = np.flatnonzero(df[col_name] == category_name)tôi biết chính xác tiêu đề của câu hỏi yêu cầu, điều khó tìm thấy trên Internet.
ClimbsRocks

Nếu bạn chỉ muốn quay lại chỉ mục, thì chi phí của df [dftest] .index là gì? Điều này có tạo ra một khung dữ liệu trung gian (có dữ liệu có thể là gibabyte). Thế còn dftest? Không phải điều này cũng phân bổ một đối tượng trung gian rất lớn trong đó chỉ mục được trả về có thể rất nhỏ hoặc thậm chí trống rỗng. Là những điều tối ưu hóa kỳ diệu đi bằng cách sử dụng quan điểm lười biếng. Nếu không thì chắc chắn phải có một cách hiệu quả.
dùng48956

31

Có thể được thực hiện bằng cách sử dụng hàm 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

Mặc dù bạn không luôn cần chỉ mục cho một trận đấu, nhưng hãy thực hiện nếu bạn cần:

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']

2

Cách đơn giản là đặt lại chỉ mục của DataFrame trước khi lọc:

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

Bit hacky, nhưng nó nhanh chóng!


1

Trước tiên, bạn có thể kiểm tra querykhi cột mục tiêu là loại bool (PS: về cách sử dụng nó, vui lòng kiểm tra liên kết )

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

Sau khi chúng tôi lọc df gốc theo cột Boolean, chúng tôi có thể chọn chỉ mục.

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

Ngoài ra gấu trúc có nonzero, chúng tôi chỉ cần chọn vị trí của Truehàng và sử dụng nó cắt lát DataFramehoặcindex

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

1

Nếu bạn chỉ muốn sử dụng đối tượng dataframe của mình một lần, hãy sử dụng:

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

0

Tôi mở rộng câu hỏi này đó là làm thế nào để nhận được row, columnvaluecủa tất cả các giá trị trận đấu?

đây là giải pháp:

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]

Đầu ra:

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


row  col        name
0    1           dog
2    0         Puppy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.