Koşul karşılanırsa Numpy öğelerini değiştirme


94

Bir koşul karşılanırsa her bir öğenin 1 veya 0 olarak değiştirilmesini sağlayacak şekilde değiştirmem gereken büyük bir uyuşuk dizim var (daha sonra piksel maskesi olarak kullanılacaktır). Dizide yaklaşık 8 milyon öğe var ve mevcut yöntemim azaltma hattı için çok uzun sürüyor:

for (y,x), value in numpy.ndenumerate(mask_data): 

    if mask_data[y,x]<3: #Good Pixel
        mask_data[y,x]=1
    elif mask_data[y,x]>3: #Bad Pixel
        mask_data[y,x]=0

Bunu hızlandıracak uyuşuk bir işlev var mı?


1
Ne olmasını istiyorsun eğer mask_data[y,x]==3?
DSM

İyi nokta, bu yine de kötü bir piksel olacaktır. Koşulu şu şekilde değiştireceğimif mask_data[y,x]>=3:
ChrisFro

Yanıtlar:


128
>>> import numpy as np
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[4, 2, 1, 1],
       [3, 0, 1, 2],
       [2, 0, 1, 1],
       [4, 0, 2, 3],
       [0, 0, 0, 2]])
>>> b = a < 3
>>> b
array([[False,  True,  True,  True],
       [False,  True,  True,  True],
       [ True,  True,  True,  True],
       [False,  True,  True, False],
       [ True,  True,  True,  True]], dtype=bool)
>>> 
>>> c = b.astype(int)
>>> c
array([[0, 1, 1, 1],
       [0, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 1, 1, 0],
       [1, 1, 1, 1]])

Bunu şu şekilde kısaltabilirsiniz:

>>> c = (a < 3).astype(int)

2
bu, bazı sütunları ayırmadan ve sonra tekrar atamadan belirli sütunlarda nasıl yapılır? örneğin, koşullar karşılandığında yalnızca [2, 3] sütunlarındaki öğeler değeri değiştirmeli, diğer sütunlar ise koşullar karşılansa da sağlanmasa da değişmeyecektir.
kuixiong

Doğru, ancak yalnızca sıfırlar ve birler durumunda. Aşağıda daha genel yanıtı görün (verimlilik maliyetinde)
borgr

89
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[0, 3, 3, 2],
       [4, 1, 1, 2],
       [3, 4, 2, 4],
       [2, 4, 3, 0],
       [1, 2, 3, 4]])
>>> 
>>> a[a > 3] = -101
>>> a
array([[   0,    3,    3,    2],
       [-101,    1,    1,    2],
       [   3, -101,    2, -101],
       [   2, -101,    3,    0],
       [   1,    2,    3, -101]])
>>>

Örneğin, boole dizileriyle indeksleme konusuna bakın .


3
harika şeyler, teşekkürler! Değiştirdiğiniz değere atıfta bulunmak istiyorsanız, gibi bir şey kullanabilirsiniz a[a > 3] = -101+a[a > 3].
pexmar

1
@pexmar Eğer a[a > 3] = -101+a[a > 3]yerine a[a > 3] += -101yaparsanız, büyük olasılıkla bellek sızıntısı ile karşı karşıya kalacaksınız.
Samuel Prevost

1
pexmar'ın sorduğu gibi değiştirdiğiniz değere nasıl atıfta bulunuyorsunuz?
Juan

34

En hızlı (ve en esnek) yol , bir maskeye göre iki dizi arasında seçim yapan np.where'i kullanmaktır (doğru ve yanlış değerler dizisi):

import numpy as np
a = np.random.randint(0, 5, size=(5, 4))
b = np.where(a<3,0,1)
print('a:',a)
print()
print('b:',b)

hangisi üretecek:

a: [[1 4 0 1]
 [1 3 2 4]
 [1 0 2 1]
 [3 1 0 0]
 [1 4 0 1]]

b: [[0 1 0 0]
 [0 1 0 1]
 [0 0 0 0]
 [1 0 0 0]
 [0 1 0 0]]

1
Koşul yerine getirilmezse hiçbir şeyle değiştirmek istemezsem en iyi yol ne olur? Örneğin, orijinal numarayı olduğu gibi bırakmazsanız, yalnızca koşul karşılandığında sağlanan değerle değiştirin ....
Abhishek Sengupta

1
Daha küçük daha sonra 3 olduğu bir tüm değerleri, yerine ve o kullanımı gibi kalanını tutmaka[a<3] = 0
Markus Dutschke

3

Maske dizinizi bunun gibi tek adımda oluşturabilirsiniz

mask_data = input_mask_data < 3

Bu, daha sonra piksel maskesi olarak kullanılabilen bir boole dizisi oluşturur. Girdi dizisini (kodunuzdaki gibi) değiştirmediğimizi, ancak maske verilerini tutmak için yeni bir dizi oluşturduğumuzu unutmayın - bunu bu şekilde yapmanızı tavsiye ederim.

>>> input_mask_data = np.random.randint(0, 5, (3, 4))
>>> input_mask_data
array([[1, 3, 4, 0],
       [4, 1, 2, 2],
       [1, 2, 3, 0]])
>>> mask_data = input_mask_data < 3
>>> mask_data
array([[ True, False, False,  True],
       [False,  True,  True,  True],
       [ True,  True, False,  True]], dtype=bool)
>>> 

1
Evet. OP gerçekten 0'lar ve 1'ler istiyorsa, .astype(int)veya kullanabilir *1, ancak bir dizi Trueve Falseolduğu kadar iyidir.
DSM

-4

Sorunuzu anladığımdan emin değilim, ama yazarsanız:

mask_data[:3, :3] = 1
mask_data[3:, 3:] = 0

Bu, x ve y indeksleri 3'ten küçük olan tüm maske verilerinin 1'e eşit ve geri kalan tüm değerlerin 0'a eşit olmasını sağlayacaktır.

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.