Panda Python: ottieni l'indice delle righe la cui colonna corrisponde a un determinato valore


277

Dato un DataFrame con una colonna "BoolCol", vogliamo trovare gli indici del DataFrame in cui i valori per "BoolCol" == True

Al momento ho il modo iterante di farlo, che funziona perfettamente:

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

Ma questo non è il modo corretto del panda di farlo. Dopo alcune ricerche, sto attualmente usando questo codice:

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

Questo mi dà un elenco di indici, ma non corrispondono, quando li controllo facendo:

df.iloc[i]['BoolCol']

Il risultato è in realtà falso !!

Quale sarebbe il modo corretto dei panda per farlo?

Risposte:


429

df.iloc[i]restituisce la ithriga di df. inon fa riferimento all'etichetta dell'indice, iè un indice basato su 0.

Al contrario, l'attributo indexrestituisce etichette di indice effettive , non indici di riga numerici:

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

o equivalentemente,

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

Puoi vedere la differenza abbastanza chiaramente giocando con un DataFrame con un indice non predefinito che non è uguale alla posizione numerica della riga:

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]

Se si desidera utilizzare l'indice ,

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

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

quindi puoi selezionare le righe usando locinvece diiloc :

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

[3 rows x 1 columns]

Nota che locpuò anche accettare array booleani :

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

[3 rows x 1 columns]

Se hai un array booleano maske hai bisogno di valori di indice ordinali, puoi calcolarli usandonp.flatnonzero :

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

Utilizzare df.ilocper selezionare le righe per indice ordinale:

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

9
Ancora un altro modo è fare df.query('BoolCol').
Phillip Cloud,

3
So che questo è vecchio, ma mi chiedo se c'è un modo semplice per ottenere i numeri di indice basati su 0 da una query. Ho bisogno dei numeri iloc perché desidero selezionare alcune righe prima e dopo una riga che soddisfa una determinata condizione. Quindi il mio piano era di ottenere gli indici 0 delle righe che soddisfano la condizione e quindi creare sezioni da usare in iloc (). L'unica cosa che vedo è get_loc, ma non può accettare un array.
Sheridp,

3
@sheridp: se hai una maschera booleana, puoi trovare gli indici ordinali dove si masktrova Trueusando np.flatnonzero. Ho modificato il post sopra per mostrare cosa intendo.
unutbu,

8
Il tuo suggerimento indices = np.flatnonzero(df[col_name] == category_name)mi dà esattamente ciò che chiede il titolo della domanda, che è sorprendentemente difficile da trovare su Internet.
ClimbsRocks

Se vuoi solo indietro l'indice, qual è il sovraccarico di df [dftest] .index? Questo crea un frame di dati intermedio (i cui dati possono essere gibabyte). Che dire di Dftest? Questo non alloca anche un oggetto intermedio molto grande in cui l'indice restituito può essere molto piccolo o addirittura vuoto. Sono magicamente ottimizzati via usando viste pigre. Altrimenti sicuramente ci deve essere un modo efficiente.
user48956

31

Può essere fatto usando numpy dove () funzione:

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

Sebbene non sia sempre necessario l'indice per una corrispondenza, ma in caso di necessità:

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

Il modo semplice è ripristinare l'indice del DataFrame prima del filtraggio:

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

Un po 'confuso, ma è veloce!


1

Per prima cosa puoi controllare queryquando la colonna di destinazione è di tipo bool (PS: su come usarla, controlla il link )

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

Dopo aver filtrato il df originale per la colonna booleana, possiamo scegliere l'indice.

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

Anche i panda hanno nonzero, selezioniamo solo la posizione della Trueriga e usandola tagliamo DataFrameoindex

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

1

Se si desidera utilizzare l'oggetto dataframe solo una volta, utilizzare:

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

0

Ho esteso questa domanda che è come ottiene la row, columne valuedi tutti i valori partite?

ecco la soluzione:

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]

Produzione:

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


row  col        name
0    1           dog
2    0         Puppy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.