Python numpy.where () nasıl çalışır?


95

numpyBelgelerle oynuyorum ve araştırıyorum ve biraz sihirle karşılaştım. Yani ben bahsediyorum numpy.where():

>>> x = np.arange(9.).reshape(3, 3)
>>> np.where( x > 5 )
(array([2, 2, 2]), array([0, 1, 2]))

x > 5Bir yönteme benzer bir şey geçirebilmenizi dahili olarak nasıl başarırlar? Sanırım bununla bir ilgisi var __gt__ama ayrıntılı bir açıklama arıyorum.

Yanıtlar:


75

İçsel olarak x> 5 gibi bir şeyi bir yönteme geçirebilmenizi nasıl başarırlar?

Kısa cevap, yapmadıklarıdır.

Bir numpy dizisindeki herhangi bir mantıksal işlem, bir boole dizisi döndürür. (yani __gt__, __lt__vb. verilen koşulun doğru olduğu tüm boole dizilerini döndürür).

Örneğin

x = np.arange(9).reshape(3,3)
print x > 5

verim:

array([[False, False, False],
       [False, False, False],
       [ True,  True,  True]], dtype=bool)

Bu, if x > 5:uyuşmuş bir diziyse x, benzer bir şeyin bir ValueError oluşturmasının aynı nedenidir . Tek bir değer değil, Doğru / Yanlış değerleri dizisidir.

Ayrıca, numpy dizileri boole dizileri tarafından indekslenebilir. Örneğin , bu durumda x[x>5]verim sağlar [6 7 8].

Dürüst olmak gerekirse, aslında ihtiyacınız olan oldukça nadirdir, numpy.whereancak sadece bir boole dizisinin olduğu göstergeleri döndürür True. Genellikle basit boole indeksleme ile ihtiyacınız olanı yapabilirsiniz.


10
Sadece bu işaret etmek numpy.whereilk 2 'operasyonel modları', bir döner var indices, condition is Trueve isteğe bağlı parametreleri ise xve y(aynı şekilde şekil mevcuttur condition, bu değerleri döndürür veya bu tür şekle broadcastable!) xNe zaman condition is Trueaksi dan y. Bu, wheredaha çok yönlü hale getirir ve daha sık kullanılmasını sağlar. Teşekkürler
yiyin

1
Over ya da ' nın __getitem__sözdizimi kullanıldığında bazı durumlarda ek yük de olabilir . Yana da dilimleme desteklemek zorundadır bazı havai var. Python Pandas veri yapılarıyla çalışırken ve çok büyük sütunları mantıksal olarak indekslerken gözle görülür hız farkları gördüm. Bu gibi durumlarda, dilimlemeye ihtiyacınız yoksa, o zaman ve aslında daha iyidir. []numpy.wherenumpy.take__getitem__takewhere
ely

24

Eski Cevap biraz kafa karıştırıcı. Size ifadenizin doğru olduğu KONUMLARI (hepsini) verir.

yani:

>>> a = np.arange(100)
>>> np.where(a > 30)
(array([31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
       48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
       65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
       82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
       99]),)
>>> np.where(a == 90)
(array([90]),)

a = a*40
>>> np.where(a > 1000)
(array([26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
       43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
       60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
       77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
       94, 95, 96, 97, 98, 99]),)
>>> a[25]
1000
>>> a[26]
1040

List.index () 'e alternatif olarak kullanıyorum, ancak başka birçok kullanımı da var. Hiç 2D dizilerle kullanmadım.

http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html

Yeni Cevap Görünüşe göre kişi daha temel bir şey soruyordu.

Soru, bir işlevin (nerede gibi) neyin talep edildiğini bilmesine izin veren bir şeyi nasıl uygulayabileceğiydi.

İlk olarak, karşılaştırma operatörlerinden herhangi birini çağırmanın ilginç bir şey yaptığını unutmayın.

a > 1000
array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True`,  True,  True,  True,  True,  True,  True,  True,  True,  True], dtype=bool)`

Bu, "__gt__" yöntemini aşırı yükleyerek yapılır. Örneğin:

>>> class demo(object):
    def __gt__(self, item):
        print item


>>> a = demo()
>>> a > 4
4

Gördüğünüz gibi, "a> 4" geçerli bir koddu.

Tüm aşırı yüklenmiş işlevlerin tam listesini ve belgelerini burada bulabilirsiniz: http://docs.python.org/reference/datamodel.html

İnanılmaz olan bir şey, bunu yapmanın ne kadar basit olduğudur. Python'daki TÜM işlemler bu şekilde yapılır. A> b demek, a'ya eşdeğerdir. gt (b)!


3
Bu karşılaştırma operatörü aşırı yüklemesi, daha karmaşık mantıksal ifadelerle iyi çalışmıyor gibi görünüyor - örneğin, yapamıyorum np.where(a > 30 and a < 50)ya np.where(30 < a < 50)da oldukça anlamsız olan iki boole dizisinin mantıksal AND'sini değerlendirmeye çalışmakla sonuçlanıyor. Böyle bir durumu yazmanın bir yolu var mı np.where?
Davida

@meowsqueaknp.where((a > 30) & (a < 50))
tibalt

Neden np.where () örneğinizde bir liste döndürüyor?
Andreas Yankopolus

0

np.whereÜzerinde çağrıldığı numpy ndarray'in boyutuna eşit uzunlukta bir demet döndürür (başka bir deyişle ndim) ve her bir tuple öğesi, koşulun True olduğu ilk ndarray'deki tüm bu değerlerin indislerinin bir numpy ndarray'idir. (Lütfen boyutu şekli ile karıştırmayın)

Örneğin:

x=np.arange(9).reshape(3,3)
print(x)
array([[0, 1, 2],
      [3, 4, 5],
      [6, 7, 8]])
y = np.where(x>4)
print(y)
array([1, 2, 2, 2], dtype=int64), array([2, 0, 1, 2], dtype=int64))


y, 2 uzunluğunda bir demettir. Tuple'daki x.ndim1. öğe, 4'ten büyük tüm öğelerin satır numaralarını ve 2. öğe, 4'ten büyük tüm öğelerin sütun numaralarını içerir. Gördüğünüz gibi, [1,2,2 , 2] 5,6,7,8 satır numaralarına karşılık gelir ve [2,0,1,2], 5,6,7,8 sütun numaralarına karşılık gelir. Ndarray'in ilk boyut (satır bazında ).

Benzer şekilde,

x=np.arange(27).reshape(3,3,3)
np.where(x>4)


x'in 3 boyutu olduğundan 3 uzunluğunda bir demet döndürecektir.

Ama bekleyin, np.where için daha fazlası var!

iki ek argüman eklendiğinde np.where; yukarıdaki demet ile elde edilen tüm bu ikili satır-sütun kombinasyonları için bir değiştirme işlemi yapacaktır.

x=np.arange(9).reshape(3,3)
y = np.where(x>4, 1, 0)
print(y)
array([[0, 0, 0],
   [0, 0, 1],
   [1, 1, 1]])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.