Пандони Python: Отримайте індекс рядків, стовпець якого відповідає певному значенню


274

Давши DataFrame зі стовпцем "BoolCol", ми хочемо знайти індекси DataFrame, в яких значення для "BoolCol" == True

Наразі у мене є ітераційний спосіб зробити це, який прекрасно працює:

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

Але це не правильний спосіб панди зробити це. Після деяких досліджень я зараз використовую цей код:

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

Цей дає мені список індексів, але вони не відповідають, коли я перевіряю їх, роблячи:

df.iloc[i]['BoolCol']

Результат насправді помилковий !!

Який би спосіб Pandas це зробити?

Відповіді:


427

df.iloc[i]повертає ithрядок df. iне посилається на мітку індексу, iце індекс на основі 0.

На відміну від цього, атрибут indexповертає фактичні мітки індексу , а не числові рядкові індекси:

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

або рівнозначно,

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

Різницю можна помітити досить чітко, граючи з DataFrame з індексом за замовчуванням, який не дорівнює чисельній позиції рядка:

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]

Якщо ви хочете використовувати індекс ,

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

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

тоді ви можете вибрати рядки, використовуючи locзамістьiloc :

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

[3 rows x 1 columns]

Зауважте, що locтакож можна приймати булові масиви :

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

[3 rows x 1 columns]

Якщо у вас є булева масив, maskі вам потрібні порядкові значення індексу, ви можете обчислити їх, використовуючиnp.flatnonzero :

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

Використовуйте df.ilocдля вибору рядків за порядковим індексом:

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

9
Ще інший спосіб - це зробити df.query('BoolCol').
Філліп Хмара

3
Я знаю, що це по-старому, але мені цікаво, чи існує простий спосіб отримати нульові індекси на основі запиту. Мені потрібні номери iloc, тому що я хочу вибрати рядки до і після ряду, який відповідає певній умові. Тож мій план полягав у тому, щоб отримати 0-індекси рядків, що відповідають умові, а потім створити фрагменти для використання в iloc (). Єдине, що я бачу, це get_loc, але він не може прийняти масив.
sheridp

3
@sheridp: Якщо у вас булева маска, ви можете знайти порядкові індекси, де maskце Trueвикористовується, використовуючи np.flatnonzero. Я редагував публікацію вище, щоб показати, що я маю на увазі.
unutbu

8
Ваша пропозиція дає indices = np.flatnonzero(df[col_name] == category_name)мені якраз те, що запитує назва запитання, яке напрочуд важко знайти в Інтернеті.
ClimbsRocks

Якщо ви хочете повернути лише індекс, що таке накладні витрати df [dftest] .index? Чи створює це проміжний кадр даних (дані якого можуть бути гібабайти). Що з dftest? Чи це також не виділяє дуже великий проміжний об'єкт, де повернутий індекс може бути дуже маленьким або навіть порожнім. Це магічно оптимізовано за допомогою лінивих поглядів. Якщо ні, то, безумовно, повинен бути ефективний спосіб.
user48956

31

Це можна зробити за допомогою функції numpy, де ():

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

Хоча вам не завжди потрібен індекс на відповідність, але майте на увазі, якщо вам потрібно:

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

Простий спосіб - скинути індекс DataFrame перед фільтруванням:

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

Трохи хакі, але це швидко!


1

Спочатку ви можете перевірити, queryколи вводиться цільовий стовпець bool (PS: про те, як ним користуватися, перевірте посилання )

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

Після того, як ми відфільтруємо оригінальний df за булевим стовпцем, ми можемо вибрати індекс.

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

Також панди є nonzero, ми просто вибрати позицію в Trueрядку і використовувати його Нарізати DataFrameабоindex

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

1

Якщо ви хочете використовувати ваш об'єкт фрейму даних лише один раз, використовуйте:

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

0

Я продовжив це питання , який , як отримує row, columnі valueвсі цінності сірників?

ось рішення:

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]

Вихід:

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


row  col        name
0    1           dog
2    0         Puppy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.