Python Pandas: obtenga el índice de filas cuya columna coincide con cierto valor

277

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

Actualmente tengo la forma iterativa de 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 panda para hacerlo. Después de un poco de investigación, actualmente estoy usando este código:

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

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

df.iloc[i]['BoolCol']

¡El resultado es en realidad falso!

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

Quiero insignias
fuente

Respuestas:

429

df.iloc[i]devuelve la ithfila de df. ino se refiere a la etiqueta del índice, ies un índice basado en 0.

Por el contrario, el atributo indexdevuelve etiquetas de índice reales , no índices numéricos de fila:

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

o equivalente,

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

Puede ver la diferencia con bastante claridad jugando 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 usando en loclugar deiloc :

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

[3 rows x 1 columns]

Tenga en cuenta que loctambié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 tiene una matriz booleana mask, y necesita valores de índice ordinales, puede calcularlos usandonp.flatnonzero :

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

Use df.ilocpara seleccionar filas por índice ordinal:

In [113]: df.iloc[np.flatnonzero(df['BoolCol'])]
Out[113]: 
   BoolCol
10    True
40    True
50    True
unutbu
fuente
9
Otra forma más es hacerlo df.query('BoolCol').
Phillip Cloud
3
Sé que esto es antiguo, pero me pregunto si hay una manera fácil de obtener los números de índice basados ​​en 0 de una consulta. Necesito los números iloc porque quiero seleccionar algunas filas antes y después de que una fila cumpla una determinada condición. Entonces, mi plan era obtener los índices 0 de las filas que cumplan la condición y luego crear cortes para usar en iloc (). Lo único que veo es get_loc, pero no puede tomar una matriz.
sheridp
3
@sheridp: si tiene una máscara booleana, puede encontrar los índices ordinales donde maskestá Trueutilizando np.flatnonzero. He editado la publicación anterior para mostrar lo que quiero decir.
unutbu
8
Su sugerencia indices = np.flatnonzero(df[col_name] == category_name)me da exactamente lo que pide el título de la pregunta, que es sorprendentemente difícil de encontrar en Internet.
ClimbsRocks
Si solo desea recuperar el índice, ¿cuál es la sobrecarga de df [dftest] .index? ¿Crea esto un marco de datos intermedio (cuyos datos pueden ser gibabytes)? ¿Qué hay de dftest? ¿No asigna esto también un objeto intermedio muy grande donde el índice devuelto puede ser muy pequeño o incluso vacío? ¿Están estos optimizados mágicamente usando vistas perezosas? Si no, entonces seguramente debe haber una manera eficiente.
user48956
31

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 necesita un índice para una coincidencia, en caso de que necesite:

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
fuente
2

La forma simple es restablecer el índice del DataFrame antes de filtrar:

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

Poco hacky, pero es rápido!

Ben Druitt
fuente
1

Primero puede verificar querycuándo la columna de destino es de tipo bool (PD: sobre cómo usarla, verifique el 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 elegir el índice.

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

También tienen pandas nonzero, solo seleccionamos la posición de la Truefila y usándola cortamos el DataFrameoindex

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

Si desea usar su objeto de marco de datos solo una vez, use:

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

Extendí esta pregunta es que cómo obtiene el row, columny valuede todo valor partidos?

Aquí hay solución:

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]

Salida:

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


row  col        name
0    1           dog
2    0         Puppy
Carson
fuente