Ich verwende Pandas-Datenrahmen und möchte eine neue Spalte als Funktion vorhandener Spalten erstellen. Ich habe keine gute Diskussion über den Geschwindigkeitsunterschied zwischen df.apply()und gesehen np.vectorize(), also dachte ich, ich würde hier fragen.
Die Pandas- apply()Funktion ist langsam. np.vectorize()Nach dem apply(), was ich gemessen habe (siehe unten in einigen Experimenten), ist die Verwendung 25x schneller (oder mehr) als die Verwendung der DataFrame-Funktion , zumindest auf meinem 2016 MacBook Pro. Ist das ein erwartetes Ergebnis und warum?
Angenommen, ich habe den folgenden Datenrahmen mit NZeilen:
N = 10
A_list = np.random.randint(1, 100, N)
B_list = np.random.randint(1, 100, N)
df = pd.DataFrame({'A': A_list, 'B': B_list})
df.head()
# A B
# 0 78 50
# 1 23 91
# 2 55 62
# 3 82 64
# 4 99 80
Angenommen, ich möchte eine neue Spalte als Funktion der beiden Spalten Aund erstellen B. Im folgenden Beispiel verwende ich eine einfache Funktion divide(). Um die Funktion anzuwenden, kann ich entweder df.apply()oder verwenden np.vectorize():
def divide(a, b):
if b == 0:
return 0.0
return float(a)/b
df['result'] = df.apply(lambda row: divide(row['A'], row['B']), axis=1)
df['result2'] = np.vectorize(divide)(df['A'], df['B'])
df.head()
# A B result result2
# 0 78 50 1.560000 1.560000
# 1 23 91 0.252747 0.252747
# 2 55 62 0.887097 0.887097
# 3 82 64 1.281250 1.281250
# 4 99 80 1.237500 1.237500
Wenn ich mich Nauf reale Größen wie 1 Million oder mehr erhöhe , np.vectorize()stelle ich fest, dass dies 25x schneller oder mehr ist als df.apply().
Unten finden Sie einen vollständigen Benchmarking-Code:
import pandas as pd
import numpy as np
import time
def divide(a, b):
if b == 0:
return 0.0
return float(a)/b
for N in [1000, 10000, 100000, 1000000, 10000000]:
print ''
A_list = np.random.randint(1, 100, N)
B_list = np.random.randint(1, 100, N)
df = pd.DataFrame({'A': A_list, 'B': B_list})
start_epoch_sec = int(time.time())
df['result'] = df.apply(lambda row: divide(row['A'], row['B']), axis=1)
end_epoch_sec = int(time.time())
result_apply = end_epoch_sec - start_epoch_sec
start_epoch_sec = int(time.time())
df['result2'] = np.vectorize(divide)(df['A'], df['B'])
end_epoch_sec = int(time.time())
result_vectorize = end_epoch_sec - start_epoch_sec
print 'N=%d, df.apply: %d sec, np.vectorize: %d sec' % \
(N, result_apply, result_vectorize)
# Make sure results from df.apply and np.vectorize match.
assert(df['result'].equals(df['result2']))
Die Ergebnisse sind unten gezeigt:
N=1000, df.apply: 0 sec, np.vectorize: 0 sec
N=10000, df.apply: 1 sec, np.vectorize: 0 sec
N=100000, df.apply: 2 sec, np.vectorize: 0 sec
N=1000000, df.apply: 24 sec, np.vectorize: 1 sec
N=10000000, df.apply: 262 sec, np.vectorize: 4 sec
Wenn np.vectorize()im Allgemeinen immer schneller ist als df.apply(), warum wird dann np.vectorize()nicht mehr erwähnt? Ich sehe immer nur StackOverflow-Beiträge, die sich auf Folgendes beziehen df.apply():
Pandas erstellen eine neue Spalte basierend auf Werten aus anderen Spalten
Wie verwende ich die Pandas-Funktion "Anwenden" auf mehrere Spalten?
So wenden Sie eine Funktion auf zwei Spalten des Pandas-Datenrahmens an
np.vectorizeist im Grunde eine Python-forSchleife (es ist eine bequeme Methode) undapplymit einem Lambda auch in Python-Zeit