Python Panda’s: verkrijg een index van rijen waarvan de kolom overeenkomt met een bepaalde waarde

Gegeven een DataFrame met een kolom “BoolCol”, willen we de indexen van het DataFrame vinden waarin de waarden voor “BoolCol” == True

Ik heb momenteel de iteratieve manier om het te doen, wat perfect werkt:

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

Maar dit is niet de juiste manier van panda’s om het te doen.
Na wat onderzoek gebruik ik momenteel deze code:

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

Deze geeft me een lijst met indexen, maar ze komen niet overeen, als ik ze controleer door te doen:

df.iloc[i]['BoolCol']

Het resultaat is eigenlijk False!!

Wat zou de juiste manier van Panda’s zijn om dit te doen?


Antwoord 1, autoriteit 100%

df.iloc[i]retourneert de ithrij van df. iverwijst niet naar het indexlabel, iis een op 0 gebaseerde index.

Daarentegen het kenmerk indexgeeft daadwerkelijke indexlabelsterug, geen numerieke rij-indexen:

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

of gelijkwaardig,

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

Je kunt het verschil heel duidelijk zien door met een DataFrame te spelen met
een niet-standaard index die niet gelijk is aan de numerieke positie van de rij:

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]

Als u de index wilt gebruiken,

In [56]: idx = df.index[df['BoolCol']]
In [57]: idx
Out[57]: Int64Index([10, 40, 50], dtype='int64')

dan kun je de rijen selecteren met locin plaats van iloc:

In [58]: df.loc[idx]
Out[58]: 
   BoolCol
10    True
40    True
50    True
[3 rows x 1 columns]

Merk op dat locook booleaanse arrays kan accepteren:

In [55]: df.loc[df['BoolCol']]
Out[55]: 
   BoolCol
10    True
40    True
50    True
[3 rows x 1 columns]

Als je een booleaanse array hebt, mask, en ordinale indexwaarden nodig hebt, kun je deze berekenen met np.flatnonzero:

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

Gebruik df.ilocom rijen te selecteren op ordinale index:

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

Antwoord 2, autoriteit 7%

Kan worden gedaan met de functie 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

Hoewel u niet altijd index voor een match nodig hebt, maar Incase als u nodig hebt:

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

Antwoord 3, Autoriteit 3%

Als u uw dataframe-object slechts één keer wilt gebruiken, gebruikt u:

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

Antwoord 4

Eenvoudige manier is om de index van het dataframe te resetten voorafgaand aan het filteren:

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

Bit Hacky, maar het is snel!


Antwoord 5

Eerst kunt u querycontroleren wanneer de doelkolom type bool(PS: over hoe u het kunt gebruiken, controleer Link )

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

Nadat we de originele df hebben gefilterd op de Booleaanse kolom, kunnen we de index kiezen.

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

Ook panda’s hebben nonzero, we selecteren gewoon de positievan de rij Trueen gebruiken deze om de DataFrameof index

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

Antwoord 6

Ik heb deze vraag uitgebreid: hoe krijg je de row, columnen valuevan alle overeenkomstenwaarde?

hier is de oplossing:

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]

Uitvoer:

         0        1       2
0       cat      dog        
1  goldfish           kitten
2     Puppy  hamster   mouse
row  col        name
0    1           dog
2    0         Puppy

Other episodes