Ich habe ein paar Dutzend Bedingungen (z. B. foo > bar
), die ich auf ~ 1MM Zeilen eines DataFrame
bewerten muss, und das prägnanteste Um dies zu schreiben, speichern Sie diese Bedingungen als eine Liste von Strings und erstellen Sie eine DataFrame
boolesche Ergebnisse (eine Zeile pro Datensatz x eine Spalte pro Bedingung). (Benutzereingabe ist nicht ausgewertet.)Wann DataFrame.eval() im Vergleich zu Pandas.eval() oder Python eval()
Auf der Suche nach vorzeitiger Optimierung, ich versuche, um zu bestimmen, ob ich diese Bedingungen für die Bewertung innerhalb DataFrame
(zB schreiben soll, df.eval("foo > bar")
oder es wie in eval("df.foo > df.bar")
zu python verlassen
nach den documentation on enhancing eval performance.
Sie sollten nicht eval() verwenden, für einfache Ausdrücke oder Ausdrücke mit kleinem Datenrahmen In der Tat, eval() ist viele Aufträge von Größe langsamer für kleinere Ausdrücke/Objekte als plain ol ' Python. Eine gute Faustregel ist, dass Sie eval() nur verwenden, wenn Sie einen DataFrame mit mehr als 10.000 Zeilen haben.
Es wäre schön, Lage sein, die df.eval("foo > bar")
Syntax zu verwenden, da meine Liste ein wenig mehr lesbar sein würde, aber ich kann nicht immer einen Fall, wo es nicht langsamer ist zu bewerten. Die Dokumentation zeigt Beispiele wo pandas.eval()
ist schneller als Python eval()
(die meiner Erfahrung entspricht) aber keine für DataFrame.eval()
(die als 'Experimental' aufgeführt ist).
Zum Beispiel ist DataFrame.eval()
noch ein klarer Verlierer in einem nicht einfachen Ausdruck auf eine groß ish DataFrame
:
import pandas as pd
import numpy as np
import numexpr
import timeit
someDf = pd.DataFrame({'a':np.random.uniform(size=int(1e6)), 'b':np.random.uniform(size=int(1e6))})
%timeit -n100 someDf.eval("a**b - a*b > b**a - b/a") # DataFrame.eval() on notional expression
%timeit -n100 eval("someDf['a']**someDf['b'] - someDf['a']*someDf['b'] > someDf['b']**someDf['a'] - someDf['b']/someDf['a']")
%timeit -n100 pd.eval("someDf.a**someDf.b - someDf.a*someDf.b > someDf.b**someDf.a - someDf.b/someDf.a")
100 loops, best of 3: 29.9 ms per loop
100 loops, best of 3: 18.7 ms per loop
100 loops, best of 3: 15.4 ms per loop
So ist der Nutzen von DataFrame.eval()
lediglich die Eingabe zu vereinfachen, oder können wir Umstände identifizieren wo ist die Verwendung dieser Methode tatsächlich schneller?
Gibt es noch andere Richtlinien für die Verwendung welche eval()
? (Ich bin mir bewusst, dass pandas.eval()
nicht den vollständigen Satz von Operationen nicht unterstützt.)
pd.show_versions()
INSTALLED VERSIONS
------------------
commit: None
python: 3.5.1.final.0
python-bits: 64
OS: Windows
OS-release: 7
machine: AMD64
processor: Intel64 Family 6 Model 63 Stepping 2, GenuineIntel
byteorder: little
LC_ALL: None
LANG: en_US
pandas: 0.18.0
nose: 1.3.7
pip: 8.1.2
setuptools: 20.3
Cython: 0.23.4
numpy: 1.10.4
scipy: 0.17.0
statsmodels: None
xarray: None
IPython: 4.1.2
sphinx: 1.3.1
patsy: 0.4.0
dateutil: 2.5.3
pytz: 2016.2
blosc: None
bottleneck: 1.0.0
tables: 3.2.2
numexpr: 2.5
matplotlib: 1.5.1
openpyxl: 2.3.2
xlrd: 0.9.4
xlwt: 1.0.0
xlsxwriter: 0.8.4
lxml: 3.6.0
bs4: 4.4.1
html5lib: None
httplib2: None
apiclient: None
sqlalchemy: 1.0.12
pymysql: None
psycopg2: None
jinja2: 2.8
boto: 2.39.0
danke für das Update - ich konnte keine Probleme in Ihrer "Infrastruktur" sehen. Ich denke, der beste Ansatz ist, die Geschwindigkeit zu testen, wie Sie es bei Ihren realen Daten getan haben. Sie könnten auch einen kleinen "Übersetzer" schreiben, der Ausdrücke von 'df.eval()' nach 'pd.eval()' Syntax – MaxU
@MaxU übersetzt, das ist eine gute Idee, danke ... im Grunde würde ich nur Variablennamen erkennen und legen Sie "df." vor ihnen. – C8H10N4O2
Ich würde empfehlen, 'df ['colname']' Syntax zu verwenden, da es sicherer ist - wenn Sie einen _risky_ Spaltennamen haben (reservierte Python-Attribute, wie 'id', Spaltennamen mit Leerzeichen usw.) – MaxU