2016-06-28 1 views
9

I einen pandas Rahmen einer dieser ähnlichen haben:Finden einer Array-Elementen Lage in einer Spalte pandas Rahmen (aka pd.series)

import pandas as pd 
import numpy as np 

data = {'Col1' : [4,5,6,7], 'Col2' : [10,20,30,40], 'Col3' : [100,50,-30,-50], 'Col4' : ['AAA', 'BBB', 'AAA', 'CCC']} 

df = pd.DataFrame(data=data, index = ['R1','R2','R3','R4']) 

    Col1 Col2 Col3 Col4 
R1  4 10 100 AAA 
R2  5 20 50 BBB 
R3  6 30 -30 AAA 
R4  7 40 -50 CCC 

Da eine Reihe von Zielen:

target_array = np.array(['AAA', 'CCC', 'EEE']) 

I möchte die Zellelemente Indizes in Col4, die auch in der target_array erscheinen.

Ich habe versucht, eine dokumentierte Antwort zu finden, aber es scheint jenseits meiner Fähigkeiten ... Hat jemand einen Rat?

P.S. Übrigens kann ich für diesen speziellen Fall ein Ziel-Array eingeben, dessen Elemente die Datenrahmen-Indexnamen array(['R1', 'R3', 'R5']) sind. Wäre es so einfacher?

Edit 1:

Vielen Dank für all die großen Antworten. Leider kann ich nur einen auswählen, aber jeder scheint @Divakar als den besten zu bezeichnen.

df.loc[df.Col4.isin(target_array)].index 

EDIT:

Ich lief drei Optionen: Noch sollten Sie verfügbar piRSquared und MAXU Geschwindigkeitsvergleiche für alle Möglichkeiten

Antwort

10

können Sie verwenden NumPy's in1d -

df.index[np.in1d(df['Col4'],target_array)] 

Erklärung

1) Erstellen Sie eine 1D Maske zu jeder Zeile entsprechenden uns sagen, ob es eine Übereinstimmung zwischen col4's Element und jedes Element in target_array:

mask = np.in1d(df['Col4'],target_array) 

2) Verwenden Sie die Maske gültigen Indizes aus dem Datenrahmen als endgültige Ausgabe zu wählen:

out = df.index[np.in1d(df['Col4'],target_array)] 
+0

Das ist schneller! – piRSquared

+0

@piRSquared Nun, ich hatte gehofft, dass ich ein NumPy-Ding bin! ;) – Divakar

+0

Ich werde das sicherlich im Hinterkopf behalten. – piRSquared

9

Dies sollte es tun sehen aus ausgewählten Antworten. Mine, Bruce Pucci und Divakar

enter image description here

Divakars war schneller durch eine große Menge. Ich würde seine auswählen.

+0

Vielen Dank für den Vergleich, es ist sehr gepflegt.Nur eine Frage: Denken Sie, dass der Datentyp (str) die Geschwindigkeit bei jeder Methode unterschiedlich beeinflusst? – Delosari

+0

Es ändert Dinge marginal. Aber die Reihenfolge bleibt gleich. – piRSquared

+0

Das ist gut zu wissen. Vielen Dank für die Antwort wieder – Delosari

5
import pandas as pd 
import numpy as np 

data = {'Col1' : [4,5,6,7], 'Col2' : [10,20,30,40], 'Col3' : [100,50,-30,-50], 'Col4' : ['AAA', 'BBB', 'AAA', 'CCC']} 
target_array = np.array(['AAA', 'CCC', 'EEE']) 

df = pd.DataFrame(data=data, index = ['R1','R2','R3','R4']) 

df['in_col'] = df['Col4'].apply(lambda x: x in target_array) 

Ist das wonach Sie gesucht haben? Dann können Sie die neue Spalte gruppieren und die True-Elemente abfragen.

+0

Vielen Dank für meine Erinnerung an das Lambda: Ich bin ziemlich neu zu Python und das ist ein sehr leistungsfähiges/flexibles Werkzeug – Delosari

4
df.index[df.Col4.isin(target_array)] 
+0

Vielen Dank für die Antwort ... es ist ein sehr gepflegter Ansatz da es nur Pandas Funktionen verwendet – Delosari

7

Aus Gründen der Vollständigkeit Ich habe zwei (.query() Varianten hinzugefügt) - meine Timings gegen 400K Reihen df:

In [63]: df.shape 
Out[63]: (400000, 4) 

In [64]: %timeit df.index[np.in1d(df['Col4'],target_array)] 
10 loops, best of 3: 35.1 ms per loop 

In [65]: %timeit df.index[df.Col4.isin(target_array)] 
10 loops, best of 3: 36.7 ms per loop 

In [66]: %timeit df.loc[df.Col4.isin(target_array)].index 
10 loops, best of 3: 47.8 ms per loop 

In [67]: %timeit df.query('@target_array.tolist() == Col4') 
10 loops, best of 3: 45.7 ms per loop 

In [68]: %timeit df.query('@target_array in Col4') 
10 loops, best of 3: 51.9 ms per loop 

Here is a similar comparison for (not in ...) and for different dtypes

+1

Vielen Dank für die Abfrageoptionen, es ist eine sehr schöne Entdeckung – Delosari