2016-01-19 8 views
6

I ile dakika ya da maksimum değerleri elde biliyoruz (tercihen düzleştirilmiş) içerir. Bu vales için endeksler aşağıdaki gibi iade edilir:Sayısal diziden azami veya en az n-öğeleri al? Bir numpy matris/vektör üzerinden</p> <pre><code>max(matrix) min(matrix) </code></pre> <p>:

Yani örn. Bir 5x5 matris olduğunda:

a = np.arange(5*5).reshape(5, 5) + 10 

# array([[10, 11, 12, 13, 14], 
#  [15, 16, 17, 18, 19], 
#  [20, 21, 22, 23, 24], 
#  [25, 26, 27, 28, 29], 
#  [30, 31, 32, 33, 34]]) 

elimden almak yoluyla maksimum değeri:

In [86]: np.max(a) # getting the max-value out of a 
Out[86]: 34 

In [87]: np.argmax(a) # index of max-value 34 is 24 if array a were flattened 
Out[87]: 24 

... ama max veya min n-elemanlarını almak için en etkili yolu nedir?

Yani 'dan bir diyelim 5 en yüksek ve 5 en düşük öğeye sahip olmak istiyorum. Bu bana [30, 31, 32, 33, 34], en yüksek 5 değer için sırasıyla [20, 21, 22, 23, 24] endeksleri için dönmelidir. Benzer şekilde 5 en düşük değer için [10, 11, 12, 13, 14] ve en düşük 5 öğenin dizinleri için [0, 1, 2, 3, 4].

Bunun için verimli ve makul bir çözüm ne olurdu?

Benim ilk fikir oldu düzleşme ve dizi sıralama ve ilk ve son 5 değerlerini alarak. Daha sonra bu değerlerin endeksleri için orijinal 2D matrisini araştırıyorum. Bu prosedür yassılaştırmaya devam etse de + sıralama çok etkili değil ... daha hızlı bir çözüm bilen var mı?

Ayrıca, orijinal 2B dizinin indislerine sahip olmak istiyorum ve düzleştirici olanı değil. Yani np.argmax(a) tarafından döndürülen 24 yerine (4, 4) olmasını istiyorum.

+1

'np.partition' (ve endeksleri için' np.argpartition') O (n) 'dir - Bu burada umabileceğin iyi olduğunu düşünüyorum.İlk önce diziyi tutturmayı gerektirir (bu sadece bir görünüm oluşturmalı ve bu yüzden herhangi bir performans cezası almamalıdır). Daha sonra, orijinal dizinizde 2D indekslerini almak için 'unravel_index' kullanabilirsiniz. Bu durumda –

cevap

4

Dizideki en büyük veya en küçük değerlerin dizinlerini almanın standart yolu np.argpartition'u kullanmaktır. Bu işlev, bir introselect algoritması kullanır ve lineer karmaşıklıkla çalışır - bu, daha büyük diziler için tam olarak sıralamadan daha iyi performans gösterir (genellikle O (n log n)).

Varsayılan olarak, bu işlev dizinin son ekseni boyunca çalışır. Dizinin tamamını değerlendirmek için ravel()'u kullanmanız gerekir.

Sonra
>>> a = np.random.randint(0, 100, size=(5, 5)) 
>>> a 
array([[60, 68, 86, 66, 9], 
     [66, 26, 83, 87, 50], 
     [41, 26, 0, 55, 9], 
     [57, 80, 71, 50, 22], 
     [94, 30, 95, 99, 76]]) 

(düzleştirilmiş) 2D dizideki beş büyük değerlerin endekslerini almak için, kullanım:

>>> i = np.argpartition(a.ravel(), -5)[-5:] # argpartition(a.ravel(), 5)[:5] for smallest 
>>> i 
array([ 2, 8, 22, 23, 20]) 

karşılık gelen 2B indeksleri geri almak için Örneğin, aşağıda rastgele dizi a var a bu pozisyonların, unravel_index kullanın:

>>> i2d = np.unravel_index(i, a.shape) 
>>> i2d 
(array([0, 1, 4, 4, 4]), array([2, 3, 2, 3, 0])) 

Sonra indeksleme i2d ile a geri verir Beş büyük değerler:

>>> a[i2d] 
array([86, 87, 95, 99, 94]) 
+0

, sıralama daha hızlıdır: '% timeit a.ravel.argpartition (-5) -> 5.5 µs' ve'% timeit a.ravel.argsort() -> 3.8 µs'. Ama tabii ki daha büyük dizilerle, bu doğru yoldur. –

İlgili konular