2009-10-26 2 views
34

तो, मान लें कि मेरे पास 100 तत्वों के साथ 100,000 फ्लोट सरणी हैं। मुझे मूल्यों की उच्चतम एक्स संख्या की आवश्यकता है, लेकिन केवल तभी जब वे वाई से अधिक हों। किसी भी तत्व से मेल नहीं खाते को 0 पर सेट किया जाना चाहिए। पायथन में ऐसा करने का सबसे तेज़ तरीका क्या होगा? आदेश बनाए रखा जाना चाहिए। ,सरणी में कम मूल्यों को शून्य करने का सबसे तेज़ तरीका?

topX = sorted([x for x in array if x > lowValY], reverse=True)[highCountX-1] 
print [x if x >= topX else 0 for x in array] 

टुकड़े में: तत्वों से अधिकांश पहले से 0.

नमूना चर की तैयारी में हैं:

array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0] 
highCountX = 3 
lowValY = .1 

अपेक्षित परिणाम:

array = [0, .25, 0, .15, .5, 0, 0, 0, 0, 0] 
+0

क्या HightCountX के लिए है? –

+0

हाईकाउंटएक्स अधिकतम संख्या में शून्य-शून्य तत्व है जो मैं सरणी – David

+0

में मौजूद होना चाहता हूं यदि यह 2 अपेक्षित परिणाम होगा: [0, 0, 0, .15, .5, 0, 0, 0, 0, 0] - हाईकाउंटएक्स परिणामस्वरूप गैर-शून्य तत्वों की संख्या को सीमित करता है। – Abgan

उत्तर

73

यह जो संचालन के इन प्रकार के लिए बहुत तेजी से होता NumPy के लिए एक विशिष्ट नौकरी, है: अब

array_np = numpy.asarray(array) 
low_values_flags = array_np < lowValY # Where values are low 
array_np[low_values_flags] = 0 # All low values set to 0 

, यदि आप केवल highCountX सबसे बड़ा तत्वों की जरूरत है, तो आप भी "भूल" कर सकते हैं छोटे तत्वों (

array_np = numpy.asarray(array) 
print numpy.sort(array_np[array_np >= lowValY])[-highCountX:] 
बेशक

, पूरे सरणी छँटाई अगर आप केवल जरूरत है कुछ तत्वों इष्टतम नहीं हो सकता है: के बजाय बड़े तत्वों की सूची 0 करने के लिए उन्हें स्थापित करने और उन्हें छँटाई) और केवल एक तरह से। आपकी जरूरतों के आधार पर, आप मानक heapq मॉड्यूल पर विचार करना चाहेंगे।

+5

अच्छा ... उचित पुस्तकालयों का उपयोग करके आप वास्तव में दूर ले सकते हैं :-) – Abgan

+0

मैं इस numPy में चल रहा हूं, अनुमान है कि मुझे इसे देखना होगा :) मदद के लिए धन्यवाद (हर कोई)। – David

+0

@ डेविड न्यूमपी वास्तव में एक आवश्यकता भरता है। मैं सुझाव दूंगा कि आप जिस ट्यूटोरियल से जुड़े हुए हैं, उससे शुरू करें: यह शायद न्यूमपी के साथ गति प्राप्त करने और इसकी सबसे महत्वपूर्ण अवधारणाओं को सीखने का सबसे तेज़ तरीका है। – EOL

5

सबसे आसान तरीका होगा यह lowValY से अधिक सभी तत्वों का चयन करता है:

[x for x in array if x > lowValY] 

इस सरणी में केवल थ्रेसहोल्ड से अधिक तत्वों की संख्या शामिल है। फिर, यह इतना छँटाई सबसे बड़ा मूल्यों शुरू में कर रहे हैं:

sorted(..., reverse=True) 

फिर एक सूची सूचकांक शीर्ष highCountX तत्वों के लिए सीमा लेता है:

sorted(...)[highCountX-1] 

अंत में, मूल सरणी एक और का उपयोग कर बाहर भर जाता है सूची समझ:

[x if x >= topX else 0 for x in array] 

एक सीमा शर्त जहां दो या अधिक समान तत्व है कि (अपने उदाहरण में) 3 उच्चतम तत्व हैं देखते हैं नहीं है। परिणामी सरणी में उस तत्व को एक से अधिक बार शामिल किया जाएगा।

अन्य सीमा स्थितियां भी हैं, जैसे len(array) < highCountX। ऐसी स्थितियों को संभालने के लिए कार्यान्वयनकर्ता को छोड़ दिया जाता है।

+1

यदि आप x> lowValY] के बजाय x> x के लिए x> lowValY के बजाय एक्स को कम करने के लिए x का उपयोग कर सकते हैं, तो इसे कॉपी किए बिना मूल सरणी पर गणना करें (यदि मूल डेटा काफी बड़ा है तो यह करने के लिए एक अच्छी बात हो सकती है)। – Abgan

+1

यह सच है। 'क्रमबद्ध() 'को शायद पूरी सूची की आवश्यकता होगी, यद्यपि। –

+0

हे, 3x तेज तो मेरा नोब कोड, लेकिन मुझे उच्च गुणवत्ता वाली सीमा को बनाए रखने के लिए समान तत्वों की आवश्यकता होगी। सरणी 20-200 तत्वों से कहीं भी होनी चाहिए ... वे वास्तव में एक बड़ी सरणी के खंड हैं जिन्हें मैं भाग में संसाधित करता हूं। अब तक सहायता के लिए धन्यवाद। – David

2

शून्य करने के लिए कुछ सीमा से नीचे सेटिंग तत्वों आसान है: (। प्लस कभी पेट() यदि आवश्यक हो तो)

array = [ x if x > threshold else 0.0 for x in array ] 

एन सबसे अधिक संख्या की आवश्यकता को थोड़ा अस्पष्ट है लेकिन,। क्या होगा यदि उदा। दहलीज के ऊपर एन + 1 बराबर संख्या? किसको छीनना है?

आप पहली सरणी सॉर्ट सकता है, तो वां तत्व के मूल्य के सीमा निर्धारित:

threshold = sorted(array, reverse=True)[N] 
array = [ x if x >= threshold else 0.0 for x in array ] 

नोट: इस समाधान पठनीयता प्रदर्शन नहीं लिए अनुकूलित है।

+0

इस मामले में, इससे कोई फर्क नहीं पड़ता कि किसको छोटा कर दिया गया है ... अधिक महत्वपूर्ण है कि हाईकाउंटएक्स का पालन किया जाता है – David

6

numpy का उपयोग करना:

# assign zero to all elements less than or equal to `lowValY` 
a[a<=lowValY] = 0 
# find n-th largest element in the array (where n=highCountX) 
x = partial_sort(a, highCountX, reverse=True)[:highCountX][-1] 
# 
a[a<x] = 0 #NOTE: it might leave more than highCountX non-zero elements 
      # . if there are duplicates 

कहाँ partial_sort हो सकता है:

def partial_sort(a, n, reverse=False): 
    #NOTE: in general it should return full list but in your case this will do 
    return sorted(a, reverse=reverse)[:n] 

अभिव्यक्ति a[a<value] = 0numpy बिना लिखा जा सकता है इस प्रकार है:

for i, x in enumerate(a): 
    if x < value: 
     a[i] = 0 
1
मानचित्र और लैम्ब्डा

आप उपयोग कर सकते हैं , यह तेजी से ई होना चाहिए nough।

new_array = map(lambda x: x if x>y else 0, array) 
0

heap का उपयोग करें।

यह समय O(n*lg(HighCountX)) में काम करता है।

import heapq 

heap = [] 
array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0] 
highCountX = 3 
lowValY = .1 

for i in range(1,highCountX): 
    heappush(heap, lowValY) 
    heappop(heap) 

for i in range(0, len(array) - 1) 
    if array[i] > heap[0]: 
     heappush(heap, array[i]) 

min = heap[0] 

array = [x if x >= min else 0 for x in array] 

deletemin जो ढेर प्रकार आप का उपयोग पर निर्भर करता है ढेर O(lg(k)) और सम्मिलन O(lg(k)) या O(1) में काम करता है।

+0

कोड सिंटैक्स का परीक्षण नहीं किया ... – Egon

7

न्यूमपी में एक विशेष मास्कडएरे क्लास है जो वास्तव में करता है। आप किसी भी पूर्व शर्त के आधार पर तत्वों को "मास्क" कर सकते हैं। यह ज़ीरो असाइन करने की तुलना में आपकी आवश्यकता का बेहतर प्रतिनिधित्व करता है: उपयुक्त होने पर numpy ऑपरेशंस मास्क किए गए मानों को अनदेखा कर देगा (उदाहरण के लिए, औसत मान ढूंढना)।

>>> from numpy import ma 
>>> x = ma.array([.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0]) 
>>> x1 = ma.masked_inside(0, 0.1) # mask everything in 0..0.1 range 
>>> x1 
masked_array(data = [-- 0.25 -- 0.15 0.5 -- -- -- -- --], 
     mask = [ True False True False False True True True True True], 
    fill_value = 1e+20) 
>>> print x.filled(0) # Fill with zeroes 
[ 0 0.25 0 0.15 0.5 0 0 0 0 0 ] 

एक addded लाभ के रूप में, नकाबपोश सरणियों अच्छी तरह से matplotlib दृश्य पुस्तकालय में समर्थित हैं यदि आप इस की जरूरत है।

Docs on masked arrays in numpy

0

एक ढेर का उपयोग करना एक अच्छा विचार है, के रूप में एगोन कहते हैं। लेकिन आप कुछ प्रयास को कम करने के heapq.nlargest फ़ंक्शन का उपयोग कर सकते हैं:

import heapq 

array = [.06, .25, 0, .15, .5, 0, 0, 0.04, 0, 0] 
highCountX = 3 
lowValY = .1 

threshold = max(heapq.nlargest(highCountX, array)[-1], lowValY) 
array = [x if x >= threshold else 0 for x in array] 
+0

मुझे यह घर का बना समाधान पसंद है जो केवल मानक मॉड्यूल का उपयोग करता है। हालांकि, इसे अपग्रेड किया जाना चाहिए ताकि वास्तव में सबसे बड़ा हाईकाउंटएक्स तत्वों को वापस कर दिया जा सके (यदि सरणी में कई तत्वों के मान 'थ्रेसहोल्ड 'हैं, तो अंतिम सरणी में बहुत से शून्य तत्व हैं)। – EOL

19
from scipy.stats import threshold 
thresholded = threshold(array, 0.5) 

:)

संबंधित मुद्दे