Python Pandas: Ruft den Index der Zeilen ab, deren Spalte einem bestimmten Wert entspricht


274

Bei einem DataFrame mit der Spalte "BoolCol" möchten wir die Indizes des DataFrame finden, in denen die Werte für "BoolCol" == True sind

Ich habe derzeit die iterative Methode, die perfekt funktioniert:

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

Dies ist jedoch nicht der richtige Weg für Panda. Nach einigen Recherchen verwende ich derzeit diesen Code:

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

Dieser gibt mir eine Liste von Indizes, aber sie stimmen nicht überein, wenn ich sie überprüfe, indem ich Folgendes tue:

df.iloc[i]['BoolCol']

Das Ergebnis ist tatsächlich falsch !!

Welches wäre der richtige Weg für Pandas, dies zu tun?

Antworten:


424

df.iloc[i]Gibt die ithZeile von zurück df. ibezieht sich nicht auf die Indexbezeichnung, iist ein 0-basierter Index.

Im Gegensatz dazu gibt das Attribut indextatsächliche Indexbezeichnungen zurück , keine numerischen Zeilenindizes :

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

oder gleichwertig,

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

Sie können den Unterschied deutlich erkennen, wenn Sie mit einem DataFrame mit einem nicht standardmäßigen Index spielen, der nicht der numerischen Position der Zeile entspricht:

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]

Wenn Sie den Index verwenden möchten ,

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

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

Dann können Sie die Zeilen auswählen, indem Sie locanstelle voniloc :

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

[3 rows x 1 columns]

Beachten Sie, dass locauch boolesche Arrays akzeptiert werden können :

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

[3 rows x 1 columns]

Wenn Sie ein boolesches Array haben maskund ordinale Indexwerte benötigen, können Sie diese berechnen mitnp.flatnonzero :

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

Verwenden Sie df.ilocdiese Option, um Zeilen anhand des Ordnungsindex auszuwählen:

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

9
Ein weiterer Weg ist zu tun df.query('BoolCol').
Phillip Cloud

3
Ich weiß, dass dies alt ist, aber ich frage mich, ob es eine einfache Möglichkeit gibt, die 0-basierten Indexnummern aus einer Abfrage zu erhalten. Ich benötige die iloc-Nummern, da ich einige Zeilen vor und nach einer Zeile auswählen möchte, die eine bestimmte Bedingung erfüllt. Mein Plan war es also, die 0-Indizes von Zeilen zu erhalten, die die Bedingung erfüllen, und dann Slices zur Verwendung in iloc () zu erstellen. Das einzige, was ich sehe, ist get_loc, aber es kann kein Array aufnehmen.
Sheridp

3
@sheridp: Wenn Sie eine boolean Maske haben, können Sie die Ordnungsindizes finden , wo das maskist Truedurch die Verwendung np.flatnonzero. Ich habe den obigen Beitrag bearbeitet, um zu zeigen, was ich meine.
Unutbu

8
Ihr Vorschlag indices = np.flatnonzero(df[col_name] == category_name)bringt mir genau das, wonach der Titel der Frage verlangt, was im Internet überraschend schwer zu finden ist.
ClimbsRocks

Wenn Sie nur den Index zurückhaben möchten, wie hoch ist der Overhead von df [dftest] .index? Erstellt dies einen Zwischendatenrahmen (dessen Daten Gibabyte sein können). Was ist mit dftest? Weist dies nicht auch ein sehr großes Zwischenobjekt zu, bei dem der zurückgegebene Index sehr klein oder sogar leer sein kann? Sind diese magisch optimiert mit faulen Ansichten. Wenn nicht, dann muss es sicher einen effizienten Weg geben.
user48956

31

Kann mit der Funktion numpy where () ausgeführt werden:

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

Sie benötigen zwar nicht immer einen Index für eine Übereinstimmung, aber falls erforderlich:

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

Eine einfache Möglichkeit besteht darin, den Index des DataFrame vor dem Filtern zurückzusetzen:

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

Etwas hackig, aber es geht schnell!


1

Zuerst können Sie überprüfen, querywann die Zielspalte vom Typ ist bool (PS: Informationen zur Verwendung finden Sie unter Link ).

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

Nachdem wir den ursprünglichen df nach der Booleschen Spalte gefiltert haben, können wir den Index auswählen.

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

Auch Pandas haben nonzero, wir wählen einfach die Position der TrueReihe und schneiden damit das DataFrameoderindex

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

1

Wenn Sie Ihr Datenrahmenobjekt nur einmal verwenden möchten, verwenden Sie:

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

0

Ich habe diese Frage erweitert, wie man das bekommt row, columnundvalue alle Spiele Wert?

Hier ist die Lösung:

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]

Ausgabe:

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


row  col        name
0    1           dog
2    0         Puppy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.