Verbessern Sie die Filtergeschwindigkeit des Pandas-Datenrahmens

9

Ich habe einen Datensatz mit 19 Spalten und ungefähr 250.000 Zeilen. Ich habe mit größeren Datensätzen gearbeitet, aber dieses Mal entschied sich Pandas, mit meinen Nerven zu spielen.

Ich habe versucht, den ursprünglichen Datensatz anhand einiger einfacher Regeln in drei Unterdatenrahmen aufzuteilen. Die Ausführung des Codes dauert jedoch lange. Etwa 15-20 Sekunden nur für die Filterung.

Gibt es eine alternative Möglichkeit, die Leistung des Codes zu verbessern?

import pandas as pd

#read dataset
df = pd.read_csv('myData.csv')

#create a dataframe with col1 10 and col2 <= 15
df1 = df[(df.col1 == 10) & (df.col2 <= 15)]
df = df[~df.isin(df1)].dropna()

#create a dataframe with col3 7 and col4 >= 4
df2 = df[(df.col3 == 7) & (df.col4 >= 4)]
df = df[~df.isin(df2)].dropna()

Am Ende habe ich die df1, df2, dfDatenrahmen mit den gefilterten Daten.

Tasos
quelle

Antworten:

15

Das zu verstehende Konzept ist, dass die Bedingung tatsächlich ein Vektor ist. Sie können also einfach die Bedingungen definieren und sie dann logisch kombinieren, z.

condition1 = (df.col1 == 10) & (df.col2 <= 15)
condition2 = (df.col3 == 7) & (df.col4 >= 4)

# at this point, condition1 and condition2 are vectors of bools

df1 = df[condition1]
df2 = df[condition2 & ~condition1]
df = df[~ (condition1 | condition2)]

Dies ist erheblich schneller, da die Bedingung nur einmal ausgewertet wird. Anschließend werden sie verwendet, um eine indizierte Suche durchzuführen und die neuen kleineren Datenrahmen zu erstellen.

Stephen Rauch
quelle
Bei Vorhandensein von None oder NaN ist nur zu beachten, dass die boolesche Logik möglicherweise nicht funktioniert.
Kawingkelvin
5

Haben Sie festgelegt, welche Zeile Ihres Codes am zeitaufwändigsten ist? Ich vermute, dass die Leitung df = df[~df.isin(df1)].dropna()lange dauern würde. Wäre es schneller, wenn Sie einfach die Negation der Bedingung verwenden, die Sie angewendet haben, um zu erhalten df1, wenn Sie Zeilen df1aus herausfiltern möchten df?

Das heißt, verwenden df = df[(df.col1 != 10) | (df.col2 > 15)].

Albert
quelle
+1 für die Empfehlung des Timings jeder Zeile
kbrose