python - Speed up comparison of floats between lists -


मेरे पास कोड का एक ब्लॉक है जो निम्न करता है:

  • एक फ्लोट से सूची, b_lst नीचे, सूचकांक इंडक्स
  • जांचें कि क्या यह फ्लोट सूचकांक i के फ्लोट के बीच स्थित है और सूची में a_lst
  • अगले एक (अनुक्रमणिका i + 1 ), यदि वह है, तो एक उप में indx को स्टोर करें एक तीसरी सूची ( c_lst ) की सूची-जहां उस उप-सूची का सूचकांक a_lst (यानी: i
  • b_lst

में सभी फ़्लोट्स के लिए पुनरावृत्ति यहाँ एक MWE है जो दिखाता है कि कोड क्या करता है:

<पूर्व> एनपी आयात समय के रूप में numpy आयात random_data (एन): # कुछ यादृच्छिक डेटा जेनरेट करें वापसी np.random.uniform (0, 10., एन)। Dolist () # डेटा सूची। # ध्यान दें कि a_lst सॉर्ट किया गया है। A_lst = np.sort (random_data (1000)) b_lst = random_data (5000) # निश्चित सूचकांक मान (int) c = 25 def func (): # कई उप-सूचियों के साथ रिक्त सूची बनाएं तत्वों के रूप में मौजूद # 'सी' सूचकांक C_lst = [[] के लिए _ श्रेणी में (लेन (a_lst [c:]) - 1)] # b_lst में प्रत्येक तत्व के लिए इंडेक्स के लिए, एएमएम एन्युमरेट (बी_लिस्ट): # ए 'लिस्ट' के तत्वों के लिए 'सी' सूचकांक से परे मैं श्रेणी में (लेन (a_lst [c:]) - 1): # जांचें कि 'elem' इस a_lst तत्व # और अगले के बीच है या नहीं। अगर a_lst [c + i] & lt; Elem & lt; = a_lst [c + (i + 1)]: # यदि यह तब 'elem' ('indx') # के सूचकांक को 'i' उप-सूची में c_lst में संग्रहीत करता है C_lst [i] .append (indx) वापसी c_lst प्रिंट func () # समय फ़ंक्शन Func_time = timeit.timeit (func, number = 10) printcfyc_time

यह कोड काम करता है जितना चाहिए, लेकिन मुझे इसके प्रदर्शन को सुधारने की आवश्यकता है क्योंकि यह मेरे बाकी कोड को धीमा कर रहा है। < / P>


जोड़ें

यह स्वीकृत उत्तर के आधार पर अनुकूलित फ़ंक्शन है। यह काफी बदसूरत है, लेकिन यह काम किया जाता है

  डीईएफ़ func_opt (): c_lst = [[] रेंज में के लिए _ (लेन (a_lst [c:]) - 1)]। C_opt = NP .searchsorted (a_lst [सी:], b_lst, पक्ष = 'छोड़') c_opt में ELEM के लिए: अगर 0 से & lt; ELEM & LT; लेन (a_lst [c:]): c_lst [ELEM-1] = np.where (c_opt == Elem) [0] .tolist () वापसी c_lst  

मेरे परीक्षणों में यह मूल फ़ंक्शन से ~ 7x तेज है।


2 जोड़ें

बहुत तेजी से np.where :

  def func_opt2 (): c_lst = [[] का उपयोग नहीं करते हैं (लेन (a_lst [c:]) - 1)] c_opt = np.searchsorted (a_lst [सी:], b_lst, पक्ष = 'छोड़') indx, गणना (c_opt) में ELEM के लिए: अगर 0 से & lt; ELEM & LT; लेन ( A_lst [c:]): c_lst [elem-1] .append (indx) वापसी c_lst  

यह मूल कार्य से 130x तेज है।


3 जोड़ें

निम्नलिखित सलाह मैंने np.searchsorted के परिणाम को .tolist () के साथ परिवर्तित कर दिया है >:

  डीईएफ़ func_opt3 (): c_lst = [[] रेंज में _ के लिए (लेन (a_lst [c:]) - 1)] c_opt = np.searchsorted (a_lst [सी:], b_lst, पक्ष = ' छोड़ दिया ') indx, गणना (c_opt में ELEM के लिए tolist ()): अगर 0 से & lt; ELEM & LT; लेन (a_lst [सी:]।): c_lst [ELEM-1] .append (indx) लौट c_lst   

यह मूल फ़ंक्शन की तुलना में ~ 470x तेज है।

आप देखना चाहते हैं पर numpy है कॉलिंग

  np.searchsorted (a_lst, b_lst, side = 'right')  

इंडेक्स की एक सरणी वापस करेगा, वही लम्बाई B_lst , आदेश को संरक्षित करने के लिए वे जो आइटम में a_lst डालने चाहिए यह बहुत तेज़ हो जाएगा, क्योंकि यह द्विआधारी खोज का उपयोग करता है और सीसी में पाशन हो जाता है। फिर आप फैंसी इंडेक्सिंग के साथ अपने उपनगर बना सकते हैं, उदा।:

  & gt; & gt; & gt; A = np.arange (1, 10) & gt; & gt; & gt; B = np.random.rand (100) * 10 & gt; & gt; & gt; C = np.searchsorted (a, b, side = 'right')> gt; & gt; & gt; बी [ग == 0] सरणी ([0.५,४६,२०,२२६, 0.४,००,४३,८७५, 0.६,२३,९८,९२५, 0.४,००,९७,६७४, 0.५,८७,६५,६०३, 0.१,४०,४५,२६४, 0.१,६९,९०,२४९, 0.७,८२,६४,०८८, 0.५,१५,०७,२५४, 0.३,१८,०८,३२७, 0.०,३८,९५,४१७, 0.९,२१,३०,०२७]) & gt; & gt; & gt; बी [ग == 1] सरणी ([१.३,४५,९९,७०९, १.४,२६,४५,७७८, १.१,३०,२५,९९६, १.२,००,९६,७२३, १.७,५७,२४,४४८, १.८,७४,४७,०५८, १.२,३४,२२,३९९, १.३,७८,०७,५५३, १.६,४१,१८,०५८, १.५,३७,४०,२९९])  

Comments