Python Pandas: Obtener el índice de las filas cuya columna coincide con un valor determinado

Dado un DataFrame con una columna "BoolCol", queremos encontrar los índices del DataFrame en los que los valores de "BoolCol" == True

Actualmente tengo la forma de iterar para hacerlo, que funciona perfectamente:

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

Pero esta no es la forma correcta de hacerlo panda's. Después de algunas investigaciones, actualmente estoy usando este código:

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

Este me da una lista de índices, pero no coinciden, cuando los compruebo haciendo:

df.iloc[i]['BoolCol']

¡¡El resultado es realmente Falso!!

¿Cuál sería la forma correcta de Pandas para hacer esto?

Solución

df.iloc[i] devuelve la ésima fila de df. i" no se refiere a la etiqueta del índice, "i" es un índice basado en 0.

En cambio, el atributo index devuelve etiquetas de índice reales, no índices numéricos de fila:

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

o de forma equivalente,

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

Puede ver la diferencia con bastante claridad si juega con un DataFrame con un índice no predeterminado que no es igual a la posición numérica de la fila':

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]

Si quieres usar el índice,

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

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

entonces puede seleccionar las filas utilizando loc en lugar de iloc:

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

[3 rows x 1 columns]

Tenga en cuenta que loc también puede aceptar matrices booleanas:

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

[3 rows x 1 columns]

Si tienes una matriz booleana, máscara, y necesitas valores de índice ordinal, puedes calcularlos usando np.flatnonzero:

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

Utiliza df.iloc para seleccionar filas por índice ordinal:

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

Se puede hacer usando la función 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

Aunque no siempre se necesita el índice para una coincidencia, pero por si acaso:

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']
Comentarios (0)

En primer lugar, puede comprobar query cuando la columna de destino es de tipo bool (PS: acerca de cómo utilizarlo por favor consulte enlace )

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

Después de filtrar el df original por la columna booleana podemos escoger el índice .

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

También los pandas tienen nonzero, simplemente seleccionamos la posición de la fila True y con ella cortamos el DataFrame o index

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