मैं पंडों के डेटाफ्रेम का उपयोग कर रहा हूं और मौजूदा कॉलम के एक फ़ंक्शन के रूप में एक नया कॉलम बनाना चाहता हूं। मैंने गति के अंतर के बारे में अच्छी चर्चा नहीं देखी है df.apply()
और np.vectorize()
इसलिए मुझे लगा कि मैं यहां पूछूंगा।
पंडों का apply()
कार्य धीमा है। जो मैंने मापा (कुछ प्रयोगों में नीचे दिखाया गया है np.vectorize()
) से, डेटाफ़्रेम फ़ंक्शन का उपयोग करने की तुलना में 25x तेज़ (या अधिक) का उपयोग कर रहा है apply()
, कम से कम मेरे 2016 मैकबुक प्रो पर। क्या यह अपेक्षित परिणाम है, और क्यों?
उदाहरण के लिए, मान लें कि मेरे पास N
पंक्तियों के साथ निम्नलिखित डेटाफ़्रेम हैं:
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
आगे मान लीजिए कि मैं दो कॉलमों के एक फ़ंक्शन के रूप में एक नया कॉलम बनाना चाहता हूं A
और B
। नीचे दिए गए उदाहरण में, मैं एक साधारण फ़ंक्शन का उपयोग करूंगा divide()
। फ़ंक्शन को लागू करने के लिए, मैं df.apply()
या तो उपयोग कर सकता हूं या 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
अगर मैं N
वास्तविक दुनिया के आकार में 1 मिलियन या उससे अधिक की वृद्धि करता हूं , तो मैं निरीक्षण करता हूं कि np.vectorize()
25x तेज या उससे अधिक है df.apply()
।
नीचे कुछ पूर्ण बेंचमार्किंग कोड दिए गए हैं:
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']))
परिणाम नीचे दर्शाए गए है:
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
यदि np.vectorize()
सामान्य रूप से हमेशा तेजी से होता है df.apply()
, तो np.vectorize()
अधिक उल्लेख क्यों नहीं किया जाता है ? मैं केवल कभी भी StackOverflow से संबंधित पोस्ट देखता हूं df.apply()
, जैसे:
पांडा अन्य स्तंभों से मानों के आधार पर नए कॉलम बनाते हैं
मैं कई कॉलमों में पंडों के 'फंक्शन' फ़ंक्शन का उपयोग कैसे करूं?
पंडों डेटाफ्रेम के दो स्तंभों के लिए एक फ़ंक्शन कैसे लागू करें
np.vectorize
मूल रूप से एक अजगरfor
पाश है (यह एक सुविधा विधि है) औरapply
एक