Wie wähle ich Zeilen aus einem DataFrame basierend auf Spaltenwerten aus?

1958

Wie wähle ich Zeilen aus einem DataFramebasierend auf Werten in einer Spalte in Python Pandas aus?

In SQL würde ich verwenden:

SELECT *
FROM table
WHERE colume_name = some_value

Ich habe versucht, die Dokumentation von pandas zu lesen, fand aber nicht sofort die Antwort.

szli
quelle
6
Dies ist ein Vergleich mit SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html, in dem Sie Pandas als SQL ausführen können.
i_thamary

Antworten:

3768

some_valueVerwenden Sie Folgendes, um Zeilen auszuwählen, deren Spaltenwert einem Skalar entspricht ==:

df.loc[df['column_name'] == some_value]

some_valuesVerwenden Sie Folgendes, um Zeilen auszuwählen, deren Spaltenwert iterierbar ist isin:

df.loc[df['column_name'].isin(some_values)]

Kombinieren Sie mehrere Bedingungen mit &:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]

Beachten Sie die Klammern. Aufgrund Pythons Betreiber Vorrangregeln , &bindet fester als <=und >=. Daher sind die Klammern im letzten Beispiel erforderlich. Ohne die Klammern

df['column_name'] >= A & df['column_name'] <= B

wird analysiert als

df['column_name'] >= (A & df['column_name']) <= B

was zu einem Wahrheitswert einer Serie führt, ist ein mehrdeutiger Fehler .


Verwenden Sie Folgendes some_value , um Zeilen auszuwählen, deren Spaltenwert nicht gleich ist !=:

df.loc[df['column_name'] != some_value]

isinGibt eine boolesche Reihe zurück. Um also Zeilen auszuwählen, deren Wert nicht in ist some_values, negieren Sie die boolesche Reihe mit ~:

df.loc[~df['column_name'].isin(some_values)]

Zum Beispiel,

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

ergibt

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Wenn Sie mehrere Werte einschließen möchten, fügen Sie diese in eine Liste (oder allgemeiner in eine iterierbare) ein und verwenden Sie isin:

print(df.loc[df['B'].isin(['one','three'])])

ergibt

     A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Beachten Sie jedoch, dass , wenn Sie wollen dies viele Male tun, ist es effizienter , einen Index zuerst zu machen, und dann verwenden df.loc:

df = df.set_index(['B'])
print(df.loc['one'])

ergibt

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

oder, um mehrere Werte aus dem Index aufzunehmen, verwenden Sie df.index.isin:

df.loc[df.index.isin(['one','two'])]

ergibt

       A  C   D
B              
one  foo  0   0
one  bar  1   2
two  foo  2   4
two  foo  4   8
two  bar  5  10
one  foo  6  12
unutbu
quelle
19
Tatsächlich funktioniert auch df [df ['colume_name'] == some_value]. Aber mein erster Versuch, df.where (df ['colume_name'] == some_value), funktioniert nicht ... nicht sicher warum ...
szli
13
Wenn Sie verwenden df.where(condition), muss die Bedingung die gleiche Form haben wie df.
Unutbu
3
Diese Links können sehr nützlich sein , um viele von Ihnen: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas-dataframes
tremendows
8
Zu Ihrer Information: Wenn Sie eine Zeile basierend auf zwei (oder mehr) Beschriftungen auswählen möchten (entweder beide oder eine erforderlich), lesen
Shane
7
Da df[df['column_name'] == some_value]funktioniert, warum brauchen wir fügen .lochier?
qqqwww
313

Es gibt verschiedene Möglichkeiten, Zeilen aus einem Pandas-Datenrahmen auszuwählen:

  1. Boolesche Indizierung ( df[df['col'] == value])
  2. Positionsindizierung ( df.iloc[...])
  3. Etikettenindizierung ( df.xs(...))
  4. df.query(...) API

Im Folgenden zeige ich Ihnen jeweils Beispiele mit Ratschlägen zur Verwendung bestimmter Techniken. Angenommen, unser Kriterium ist Spalte 'A'=='foo'

(Hinweis zur Leistung: Für jeden Basistyp können wir die Dinge mithilfe der Pandas-API einfach halten oder uns außerhalb der API wagen, normalerweise in die API hinein numpy, und die Dinge beschleunigen.)


Setup
Das erste, was wir brauchen, ist die Identifizierung einer Bedingung, die als unser Kriterium für die Auswahl von Zeilen dient. Wir beginnen mit dem Fall des OP column_name == some_valueund schließen einige andere häufige Anwendungsfälle ein.

Ausleihen bei @unutbu:

import pandas as pd, numpy as np

df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})

1. Boolesche Indizierung

... Für die boolesche Indizierung muss ermittelt werden, ob der wahre Wert der 'A'Spalte jeder Zeile gleich ist 'foo', und anhand dieser Wahrheitswerte ermittelt werden, welche Zeilen beibehalten werden sollen. Normalerweise nennen wir diese Reihe eine Reihe von Wahrheitswerten mask. Das machen wir auch hier.

mask = df['A'] == 'foo'

Wir können diese Maske dann verwenden, um den Datenrahmen zu schneiden oder zu indizieren

df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Dies ist eine der einfachsten Möglichkeiten, um diese Aufgabe zu erfüllen. Wenn Leistung oder Intuitivität kein Problem darstellen, sollte dies die von Ihnen gewählte Methode sein. Wenn jedoch die Leistung ein Problem darstellt, sollten Sie eine alternative Methode zum Erstellen des in Betracht ziehen mask.


2. Positionsindizierung

Die Positionsindizierung ( df.iloc[...]) hat ihre Anwendungsfälle, aber dies ist keiner von ihnen. Um herauszufinden, wo geschnitten werden soll, müssen wir zuerst dieselbe boolesche Analyse durchführen, die wir oben durchgeführt haben. Dadurch müssen wir einen zusätzlichen Schritt ausführen, um dieselbe Aufgabe zu erfüllen.

mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

3. Etikettenindizierung

Die Indizierung von Etiketten kann sehr praktisch sein, aber in diesem Fall erledigen wir wieder mehr Arbeit ohne Nutzen

df.set_index('A', append=True, drop=False).xs('foo', level=1)

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

4. df.query()API

pd.DataFrame.queryist eine sehr elegante / intuitive Methode, um diese Aufgabe auszuführen, ist jedoch häufig langsamer. Allerdings , wenn Sie die Aufmerksamkeit auf die Timings unten zahlen, für große Daten, ist die Abfrage sehr effizient. Mehr als der Standardansatz und von ähnlicher Größe wie mein bester Vorschlag.

df.query('A == "foo"')

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Ich bevorzuge die Boolean mask

Tatsächliche Verbesserungen können vorgenommen werden, indem geändert wird, wie wir unsere erstellen Boolean mask.

maskAlternative 1
Verwenden Sie das zugrunde liegende numpyArray und verzichten Sie auf den Aufwand für die Erstellung eines anderenpd.Series

mask = df['A'].values == 'foo'

Ich werde am Ende vollständigere Zeittests zeigen, aber werfen Sie einen Blick auf die Leistungssteigerungen, die wir mit dem Beispieldatenrahmen erzielen. Zunächst betrachten wir den Unterschied bei der Erstellung dermask

%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'

5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Die Auswertung maskmit dem numpyArray ist ~ 30 mal schneller. Dies ist teilweise darauf zurückzuführen, dass die numpyBewertung häufig schneller erfolgt. Dies ist auch teilweise auf den fehlenden Overhead zurückzuführen, der zum Erstellen eines Index und eines entsprechenden pd.SeriesObjekts erforderlich ist .

Als nächstes schauen wir uns den Zeitpunkt für das Schneiden mit dem einen maskgegen den anderen an.

mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]

219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Die Leistungssteigerungen sind nicht so ausgeprägt. Wir werden sehen, ob dies gegenüber robusteren Tests Bestand hat.


maskAlternative 2
Wir hätten auch den Datenrahmen rekonstruieren können. Bei der Rekonstruktion eines Datenrahmens gibt es eine große Einschränkung - Sie müssen sich dabei um die kümmern dtypes!

Stattdessen werden df[mask]wir dies tun

pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

Wenn der Datenrahmen vom gemischten Typ ist, was unser Beispiel ist, dann sind, wenn wir df.valuesdas resultierende Array erhalten, dtype objectund folglich alle Spalten des neuen Datenrahmens von dtype object. Dies erfordert astype(df.dtypes)und tötet potenzielle Leistungssteigerungen.

%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Wenn der Datenrahmen jedoch nicht vom gemischten Typ ist, ist dies eine sehr nützliche Methode.

Gegeben

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

d1

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
6  8  7  6  4  7
7  6  2  6  6  5
8  2  8  7  5  8
9  4  7  6  1  5    

%%timeit
mask = d1['A'].values == 7
d1[mask]

179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Gegen

%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)

87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Wir haben die Zeit halbiert.


maskAlternative 3
@unutbu zeigt uns auch, wie wir pd.Series.isinjedes Element df['A']in einer Reihe von Werten berücksichtigen können. Dies ergibt dasselbe, wenn unser Wertesatz ein Satz von einem Wert ist, nämlich 'foo'. Es wird jedoch auch verallgemeinert, bei Bedarf größere Wertesätze einzuschließen. Es stellt sich heraus, dass dies immer noch ziemlich schnell ist, obwohl es eine allgemeinere Lösung ist. Der einzige wirkliche Verlust liegt in der Intuitivität für diejenigen, die mit dem Konzept nicht vertraut sind.

mask = df['A'].isin(['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Nach wie vor können wir jedoch numpydie Leistung verbessern und dabei praktisch nichts opfern. Wir werden verwendennp.in1d

mask = np.in1d(df['A'].values, ['foo'])
df[mask]

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Timing
Ich werde andere Konzepte, die in anderen Posts erwähnt werden, auch als Referenz aufnehmen.
Code unten

Jede Spalte in dieser Tabelle repräsentiert einen Datenrahmen unterschiedlicher Länge, über den wir jede Funktion testen. Jede Spalte zeigt die relative Zeit, die benötigt wird, wobei die schnellste Funktion einen Basisindex von hat 1.0.

res.div(res.min())

                         10        30        100       300       1000      3000      10000     30000
mask_standard         2.156872  1.850663  2.034149  2.166312  2.164541  3.090372  2.981326  3.131151
mask_standard_loc     1.879035  1.782366  1.988823  2.338112  2.361391  3.036131  2.998112  2.990103
mask_with_values      1.010166  1.000000  1.005113  1.026363  1.028698  1.293741  1.007824  1.016919
mask_with_values_loc  1.196843  1.300228  1.000000  1.000000  1.038989  1.219233  1.037020  1.000000
query                 4.997304  4.765554  5.934096  4.500559  2.997924  2.397013  1.680447  1.398190
xs_label              4.124597  4.272363  5.596152  4.295331  4.676591  5.710680  6.032809  8.950255
mask_with_isin        1.674055  1.679935  1.847972  1.724183  1.345111  1.405231  1.253554  1.264760
mask_with_in1d        1.000000  1.083807  1.220493  1.101929  1.000000  1.000000  1.000000  1.144175

Sie werden feststellen, dass die schnellsten Zeiten zwischen mask_with_valuesund geteilt zu werden scheinenmask_with_in1d

res.T.plot(loglog=True)

Geben Sie hier die Bildbeschreibung ein

Funktionen

def mask_standard(df):
    mask = df['A'] == 'foo'
    return df[mask]

def mask_standard_loc(df):
    mask = df['A'] == 'foo'
    return df.loc[mask]

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_values_loc(df):
    mask = df['A'].values == 'foo'
    return df.loc[mask]

def query(df):
    return df.query('A == "foo"')

def xs_label(df):
    return df.set_index('A', append=True, drop=False).xs('foo', level=-1)

def mask_with_isin(df):
    mask = df['A'].isin(['foo'])
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

Testen

res = pd.DataFrame(
    index=[
        'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
        'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
    ],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

for j in res.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in res.index:a
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        res.at[i, j] = timeit(stmt, setp, number=50)

Sonderzeitpunkt
Betrachten Sie den Sonderfall, wenn wir ein einzelnes Nichtobjekt dtypefür den gesamten Datenrahmen haben. Code unten

spec.div(spec.min())

                     10        30        100       300       1000      3000      10000     30000
mask_with_values  1.009030  1.000000  1.194276  1.000000  1.236892  1.095343  1.000000  1.000000
mask_with_in1d    1.104638  1.094524  1.156930  1.072094  1.000000  1.000000  1.040043  1.027100
reconstruct       1.000000  1.142838  1.000000  1.355440  1.650270  2.222181  2.294913  3.406735

Es stellt sich heraus, dass sich der Wiederaufbau nach ein paar hundert Reihen nicht lohnt.

spec.T.plot(loglog=True)

Geben Sie hier die Bildbeschreibung ein

Funktionen

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

def reconstruct(df):
    v = df.values
    mask = np.in1d(df['A'].values, ['foo'])
    return pd.DataFrame(v[mask], df.index[mask], df.columns)

spec = pd.DataFrame(
    index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

Testen

for j in spec.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in spec.index:
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        spec.at[i, j] = timeit(stmt, setp, number=50)
piRSquared
quelle
6
Fantastische Antwort! 2 Fragen, i) wie würde man .iloc(numpy.where(..))in diesem Schema vergleichen? ii) Würden Sie erwarten, dass die Ranglisten bei Verwendung mehrerer Bedingungen gleich sind?
Posdef
3
Für die Ausführung pd.Series.isinist zu beachten , es tut Gebrauch np.in1dunter der Haube in einem bestimmten Szenario Khash Verwendungen in anderen, und gelten implizit einen Kompromiss zwischen Kosten von Hashing gegen Leistung in bestimmten Situationen. Diese Antwort enthält mehr Details.
jpp
1
Bei 9 Screenfuls ist dies eine Überlastung für einen neuen oder sogar fortgeschrittenen Benutzer. Sie können und sollten das tl; dr im ersten Absatz selbst zusammenfassen.
smci
@piRSquared Scaling zählt Hätten Sie etwas dagegen, @piRSquared, auch veröffentlichen Sie Ihre Erfahrungen über , wie gut die tatsächlichen [{P|EXP}TIME] - und [{C|P|EXP}SPACE]- Kosten der Verwendung der oben vorgeschlagenen Formen der Block-Syntax ( die Verarbeitung top-down die gesamte Datenrahmen auf einmal) wachsen , und zwar , wenn auf einige ~1E6, ~1E9, ~1E12Zeilenzahlen skaliert ? Vielen Dank, dass Sie uns das ganze Bild gezeigt haben, Sir. Quantitative Benchmark Lesungen mit [min, Avg, MAX, StDev]immer willkommen, da sowohl die minund MAXWerte , die begleiten Mean/StDevErleichterung der Partie.
user3666197
Hervorragende Antwort! Die Abfrage hat mein Problem gelöst!
Pavlos Ponos
281

tl; dr

Die Pandas entsprechen

select * from table where column_name = some_value

ist

table[table.column_name == some_value]

Mehrere Bedingungen:

table[(table.column_name == some_value) | (table.column_name2 == some_value2)]

oder

table.query('column_name == some_value | column_name2 == some_value2')

Codebeispiel

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

Im obigen Code df[df.foo == 222]gibt 222in diesem Fall die Zeile die Zeilen basierend auf dem Spaltenwert an .

Es sind auch mehrere Bedingungen möglich:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

An dieser Stelle würde ich jedoch die Verwendung der Abfragefunktion empfehlen , da diese weniger ausführlich ist und das gleiche Ergebnis liefert:

df.query('foo == 222 | bar == 444')
imolit
quelle
5
queryist hier die einzige Antwort, die mit der Methodenverkettung kompatibel ist. Es scheint, als wäre es das Pandas-Analogon zu filterdplyr.
Berk U.
3
Hallo, in Ihrem dritten Beispiel (mehrere Spalten) denke ich, dass Sie eckige Klammern und [keine runden Klammern (an der Außenseite benötigen .
user2739472
2
Zuerst dachte ich, das wäre |für AND, aber natürlich ist es OR-Operator ...
O-9
für mehrere Bedingungen mit AND kann man tundf[condition1][condition2]
Ritwik
1
Lassen Sie dies hier, nur für den Fall, dass es für jemanden nützlich ist: Ab 0.25 kann die Abfrage mit Spaltennamen verwendet werden, deren Leerzeichen Leerzeichen enthalten, indem der Name in Backticks eingeschlossen wird:df.query('`my col` == 124')
cs95
65

Ich finde die Syntax der vorherigen Antworten überflüssig und schwer zu merken. Pandas hat die query()Methode in Version 0.13 eingeführt und ich bevorzuge sie sehr. Für Ihre Frage könnten Sie tundf.query('col == val')

Wiedergabe von http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query

In [167]: n = 10

In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))

In [169]: df
Out[169]: 
          a         b         c
0  0.687704  0.582314  0.281645
1  0.250846  0.610021  0.420121
2  0.624328  0.401816  0.932146
3  0.011763  0.022921  0.244186
4  0.590198  0.325680  0.890392
5  0.598892  0.296424  0.007312
6  0.634625  0.803069  0.123872
7  0.924168  0.325076  0.303746
8  0.116822  0.364564  0.454607
9  0.986142  0.751953  0.561512

# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

Sie können auch auf Variablen in der Umgebung zugreifen, indem Sie eine voranstellen @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
Fredcallaway
quelle
1
Sie müssen nur das Paket numexprinstallieren.
MERose
4
In meinem Fall brauchte ich ein Anführungszeichen, weil val eine Zeichenfolge ist. df.query ('col == "val"')
smerlung
28

Mehr Flexibilität .querymit pandas >= 0.25.0:

August 2019 aktualisierte Antwort

Da können pandas >= 0.25.0wir die queryMethode verwenden, um Datenrahmen mit Pandas-Methoden und sogar Spaltennamen mit Leerzeichen zu filtern. Normalerweise würden die Leerzeichen in Spaltennamen einen Fehler ergeben, aber jetzt können wir das mit einem Backtick (`) lösen, siehe GitHub :

# Example dataframe
df = pd.DataFrame({'Sender email':['[email protected]', "[email protected]", "[email protected]"]})

     Sender email
0  ex@example.com
1  reply@shop.com
2    buy@shop.com

Verwenden .querymit Methode str.endswith:

df.query('`Sender email`.str.endswith("@shop.com")')

Ausgabe

     Sender email
1  reply@shop.com
2    buy@shop.com

Wir können auch lokale Variablen verwenden, indem wir @in unserer Abfrage ein Präfix voranstellen:

domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')

Ausgabe

     Sender email
1  reply@shop.com
2    buy@shop.com
Erfan
quelle
26

Schnellere Ergebnisse können mit numpy.where erzielt werden .

Zum Beispiel mit dem Setup von unubtu -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Zeitvergleiche:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop
shivsn
quelle
24

Hier ist ein einfaches Beispiel

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111
DataByDavid
quelle
17

Zum Auswählen nur bestimmter Spalten aus mehreren Spalten für einen bestimmten Wert in Pandas:

select col_name1, col_name2 from table where column_name = some_value.

Optionen:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

oder

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
SP001
quelle
16

Um an diese berühmte Frage anzuhängen (wenn auch etwas zu spät): Sie können auch df.groupby('column_name').get_group('column_desired_value').reset_index()einen neuen Datenrahmen mit einer bestimmten Spalte mit einem bestimmten Wert erstellen. Z.B

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)

Führen Sie dies ergibt:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two
TuanDT
quelle
Gute Antwort. Ich möchte nur hinzufügen, dass der zweite (pd.DataFrame) redundant ist, da get_group()automatisch ein Datenrahmen zurückgegeben wird. Sie können auch einfach "drop = True" als Parameter von sagen reset_index(). Mit anderen Worten, es kann verkürzt werden auf: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott
7

Sie können auch .apply verwenden:

df.apply(lambda row: row[df['B'].isin(['one','three'])])

Es funktioniert tatsächlich zeilenweise (dh es wendet die Funktion auf jede Zeile an).

Die Ausgabe ist

   A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Die Ergebnisse sind die gleichen wie bei @unutbu

df[[df['B'].isin(['one','three'])]]
Vahidn
quelle