मान लें कि मेरे पास इस तरह एक np.array है:

a = [1, 3, 4, 5, 60, 43, 53, 4, 46, 54, 56, 78]

क्या उन सभी स्थानों के सूचकांक प्राप्त करने का कोई त्वरित तरीका है जहां लगातार 3 संख्याएं कुछ सीमा से ऊपर हैं? अर्थात्, कुछ सीमा th के लिए, सभी x प्राप्त करें जहां यह है:

a[x]>th and a[x+1]>th and a[x+2]>th

उदाहरण: सीमा 40 और ऊपर दी गई सूची के लिए, x [4,8,9] होना चाहिए।

बहुत धन्यवाद।

4
WangYang.Cao 6 अगस्त 2018, 10:34
"त्वरित विधि" से आपका क्या तात्पर्य है? बहुत सारे फ़ज़ के बिना टाइप करना आसान है, या अत्यधिक अनुकूलित और रात का खाना तेज़ है?
 – 
kvantour
6 अगस्त 2018, 11:17

3 जवाब

दृष्टिकोण #1

तुलना के बाद प्राप्त बूलियन ऐरे के मास्क पर convolution का प्रयोग करें -

In [40]: a # input array
Out[40]: array([ 1,  3,  4,  5, 60, 43, 53,  4, 46, 54, 56, 78])

In [42]: N = 3 # compare N consecutive numbers

In [44]: T = 40 # threshold for comparison

In [45]: np.flatnonzero(np.convolve(a>T, np.ones(N, dtype=int),'valid')>=N)
Out[45]: array([4, 8, 9])

दृष्टिकोण #2

binary_erosion का प्रयोग करें -

In [77]: from scipy.ndimage.morphology import binary_erosion

In [31]: np.flatnonzero(binary_erosion(a>T,np.ones(N, dtype=int), origin=-(N//2)))
Out[31]: array([4, 8, 9])

दृष्टिकोण #3 (विशिष्ट मामला): लगातार संख्याओं की छोटी संख्या जांचें

इतनी कम संख्या में लगातार संख्या (इस मामले में तीन) की जाँच के लिए, हम बेहतर प्रदर्शन के लिए तुलना किए गए मास्क पर slicing भी कर सकते हैं -

m = a>T
out = np.flatnonzero(m[:-2] & m[1:-1] & m[2:])

बेंच मार्किंग

दिए गए नमूने से 100000 बार-बार/टाइल वाली सरणी पर समय -

In [78]: a
Out[78]: array([ 1,  3,  4,  5, 60, 43, 53,  4, 46, 54, 56, 78])

In [79]: a = np.tile(a,100000)

In [80]: N = 3

In [81]: T = 40

# Approach #3
In [82]: %%timeit
    ...: m = a>T
    ...: out = np.flatnonzero(m[:-2] & m[1:-1] & m[2:])
1000 loops, best of 3: 1.83 ms per loop

# Approach #1
In [83]: %timeit np.flatnonzero(np.convolve(a>T, np.ones(N, dtype=int),'valid')>=N)
100 loops, best of 3: 10.9 ms per loop

# Approach #2    
In [84]: %timeit np.flatnonzero(binary_erosion(a>T,np.ones(N, dtype=int), origin=-(N//2)))
100 loops, best of 3: 11.7 ms per loop
7
Divakar 6 अगस्त 2018, 11:31
बस सोच रहा था कि क्या यह लगातार 3 से अधिक संख्याओं के लिए काम करता है?
 – 
taras
6 अगस्त 2018, 10:45
ठीक है, मैं चूक गया। IIRC, बाइनरी_एरिसन भी एक मुखौटा स्वीकार करता है, इसलिए इसे मनमाना अनुक्रम तक भी बढ़ाया जा सकता है?
 – 
taras
6 अगस्त 2018, 10:48
1
हाँ! संपादित।
 – 
Divakar
6 अगस्त 2018, 10:56

प्रयत्न:

th=40
results = [ x for x in range( len( array ) -2 )  if(array[x:x+3].min() > th) ]

जो के लिए एक सूची समझ है

th=40
results = []
for x in range( len( array ) -2 ):
    if( array[x:x+3].min() > th ):
        results.append( x )
1
U12-F̉͋̅̾̇orward 6 अगस्त 2018, 10:47

एक अन्य दृष्टिकोण, numpy.lib.stride_tricks.as_strided का उपयोग करते हुए:

in [59]: import numpy as np

In [60]: from numpy.lib.stride_tricks import as_strided

इनपुट डेटा को परिभाषित करें:

In [61]: a = np.array([ 1,  3,  4,  5, 60, 43, 53,  4, 46, 54, 56, 78])

In [62]: N = 3

In [63]: threshold = 40

परिणाम की गणना करें; q "बड़े" मानों के लिए बूलियन मास्क है।

In [64]: q = a > threshold

In [65]: result = np.all(as_strided(q, shape=(len(q)-N+1, N), strides=(q.strides[0], q.strides[0])), axis=1).nonzero()[0]

In [66]: result
Out[66]: array([4, 8, 9])

N = 4 के साथ इसे फिर से करें:

In [67]: N = 4

In [68]: result = np.all(as_strided(q, shape=(len(q)-N+1, N), strides=(q.strides[0], q.strides[0])), axis=1).nonzero()[0]

In [69]: result
Out[69]: array([8])
1
Warren Weckesser 6 अगस्त 2018, 10:51