it-swarm.com.de

Datenrahmenzeilen filtern, wenn der Wert in der Spalte in einer festgelegten Werteliste enthalten ist

Ich habe einen Python pandas DataFrame rpt:

rpt
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231')
Data columns:
STK_ID                    47518  non-null values
STK_Name                  47518  non-null values
RPT_Date                  47518  non-null values
sales                     47518  non-null values

Ich kann die Zeilen, deren Bestands-ID '600809' ist, folgendermaßen filtern: rpt[rpt['STK_ID'] == '600809']

<class 'pandas.core.frame.DataFrame'>
MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331')
Data columns:
STK_ID                    25  non-null values
STK_Name                  25  non-null values
RPT_Date                  25  non-null values
sales                     25  non-null values

und ich möchte alle Zeilen einiger Aktien zusammenfassen, z. B. ['600809','600141','600329']. Das heißt, ich möchte eine Syntax wie diese:

stk_list = ['600809','600141','600329']

rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas 

Wie kann das Ziel erreicht werden, wenn pandas den obigen Befehl nicht akzeptiert?

365
bigbug

Verwenden Sie die Methode isin. rpt[rpt['STK_ID'].isin(stk_list)].

536
BrenBarn

isin() ist ideal, wenn Sie eine Liste mit genauen Übereinstimmungen haben, aber wenn Sie eine Liste mit Teilübereinstimmungen oder Teilzeichenfolgen suchen müssen, können Sie mit der Methode str.contains und regulären Ausdrücken filtern.

Wenn wir zum Beispiel einen DataFrame zurückgeben möchten, in dem alle Bestands-IDs, die mit '600' beginnen und dann von drei beliebigen Ziffern gefolgt werden:

>>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]{3}$')] # ^ means start of string
...   STK_ID   ...                                    # [0-9]{3} means any three digits
...  '600809'  ...                                    # $ means end of string
...  '600141'  ...
...  '600329'  ...
...      ...   ...

Angenommen, wir haben jetzt eine Liste von Zeichenfolgen, mit denen die Werte in 'STK_ID' enden sollen, z.

endstrings = ['01$', '02$', '05$']

Wir können diese Zeichenfolgen mit dem regulären Ausdruck "oder" (Zeichen |) verbinden und die Zeichenfolge an str.contains übergeben, um den DataFrame zu filtern:

>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
...   STK_ID   ...
...  '155905'  ...
...  '633101'  ...
...  '210302'  ...
...      ...   ...

Schließlich kann contains die Groß-/Kleinschreibung ignorieren (indem Sie case=False festlegen), sodass Sie allgemeiner vorgehen können, wenn Sie die Zeichenfolgen angeben, die Sie abgleichen möchten.

Zum Beispiel,

str.contains('pandas', case=False)

würde mit PANDAS, PanDAs, paNdAs123 usw. übereinstimmen.

104
Alex Riley

sie können Bereiche auch verwenden, indem Sie Folgendes verwenden:

b = df[(df['a'] > 1) & (df['a'] < 5)]
42
yemu

Sie können für diese Informationen auch direkt abfragen Ihren DataFrame.

rpt.query('STK_ID in (600809,600141,600329)')

Oder suchen Sie auf ähnliche Weise nach Bereichen:

rpt.query('60000 < STK_ID < 70000')
37
bscan

Daten mit Pandas aufteilen

Bei einem Datenrahmen wie diesem:

    RPT_Date  STK_ID STK_Name  sales
0 1980-01-01       0   Arthur      0
1 1980-01-02       1    Beate      4
2 1980-01-03       2    Cecil      2
3 1980-01-04       3     Dana      8
4 1980-01-05       4     Eric      4
5 1980-01-06       5    Fidel      5
6 1980-01-07       6   George      4
7 1980-01-08       7     Hans      7
8 1980-01-09       8   Ingrid      7
9 1980-01-10       9    Jones      4

Es gibt mehrere Möglichkeiten, die Daten auszuwählen oder in Segmente aufzuteilen.

Mit .isin

Das offensichtlichste ist die Funktion .isin. Sie können eine Maske erstellen, die eine Reihe von True/False -Anweisungen enthält, die auf einen Datenrahmen wie diesen angewendet werden können:

mask = df['STK_ID'].isin([4, 2, 6])

mask
0    False
1    False
2     True
3    False
4     True
5    False
6     True
7    False
8    False
9    False
Name: STK_ID, dtype: bool

df[mask]
    RPT_Date  STK_ID STK_Name  sales
2 1980-01-03       2    Cecil      2
4 1980-01-05       4     Eric      4
6 1980-01-07       6   George      4

Das Maskieren ist die Ad-hoc-Lösung für das Problem, funktioniert jedoch in Bezug auf Geschwindigkeit und Speicher nicht immer gut.

Mit Indizierung

Indem Sie den Index auf die Spalte STK_ID setzen, können Sie das pandas integrierte Slicing-Objekt .loc verwenden.

df.set_index('STK_ID', inplace=True)
         RPT_Date STK_Name  sales
STK_ID                           
0      1980-01-01   Arthur      0
1      1980-01-02    Beate      4
2      1980-01-03    Cecil      2
3      1980-01-04     Dana      8
4      1980-01-05     Eric      4
5      1980-01-06    Fidel      5
6      1980-01-07   George      4
7      1980-01-08     Hans      7
8      1980-01-09   Ingrid      7
9      1980-01-10    Jones      4

df.loc[[4, 2, 6]]
         RPT_Date STK_Name  sales
STK_ID                           
4      1980-01-05     Eric      4
2      1980-01-03    Cecil      2
6      1980-01-07   George      4

Dies ist die schnelle Methode, auch wenn die Indizierung einige Zeit in Anspruch nehmen kann. Sie spart jedoch Zeit, wenn Sie mehrere Abfragen wie diese ausführen möchten.

Datenrahmen zusammenführen

Dies kann auch durch Zusammenführen von Datenrahmen erfolgen. Dies passt eher für ein Szenario, in dem Sie viel mehr Daten haben als in diesen Beispielen.

stkid_df = pd.DataFrame({"STK_ID": [4,2,6]})
df.merge(stkid_df, on='STK_ID')
   STK_ID   RPT_Date STK_Name  sales
0       2 1980-01-03    Cecil      2
1       4 1980-01-05     Eric      4
2       6 1980-01-07   George      4

Hinweis

Alle oben genannten Methoden funktionieren auch dann, wenn mehrere Zeilen mit demselben 'STK_ID' vorhanden sind.

22
firelynx

Sie können ähnliche Ergebnisse auch erzielen, indem Sie 'query' und @ verwenden:

z.B:

df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']})
df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]})
list_of_values = [3,6]
result= df.query("A in @list_of_values")
result
   A  B
1  6  2
2  3  3
6
akuriako

Sie können query verwenden, d. H .:

b = df.query('a > 1 & a < 5')
5
Pedro Lobito