การเปลี่ยนองค์ประกอบ Numpy หากตรงตามเงื่อนไข


94

ฉันมีอาร์เรย์จำนวนมากที่ต้องจัดการเพื่อให้แต่ละองค์ประกอบเปลี่ยนเป็น 1 หรือ 0 หากตรงตามเงื่อนไข (จะใช้เป็นพิกเซลมาสก์ในภายหลัง) อาร์เรย์มีองค์ประกอบประมาณ 8 ล้านองค์ประกอบและวิธีการปัจจุบันของฉันใช้เวลานานเกินไปสำหรับท่อลดขนาด:

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

มีฟังก์ชัน numpy ที่จะเร่งความเร็วนี้หรือไม่?


1
คุณอยากให้เกิดอะไรขึ้นถ้าmask_data[y,x]==3?
DSM

จุดดีที่ยังคงเป็นพิกเซลที่ไม่ดี ฉันจะเปลี่ยนเงื่อนไขเป็นif mask_data[y,x]>=3:
ChrisFro

คำตอบ:


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]])

คุณสามารถย่อสิ่งนี้ได้ด้วย:

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

2
จะทำให้สิ่งนี้เกิดขึ้นกับคอลัมน์เฉพาะได้อย่างไรโดยไม่ต้องแบ่งบางคอลัมน์ออกแล้วกำหนดกลับอีกครั้ง ตัวอย่างเช่นเฉพาะองค์ประกอบในคอลัมน์ [2, 3] เท่านั้นที่ควรเปลี่ยนค่าเมื่อตรงตามเงื่อนไขในขณะที่คอลัมน์อื่น ๆ จะไม่เปลี่ยนแปลงไม่ว่าจะตรงตามเงื่อนไขหรือไม่ก็ตาม
kuixiong

จริง แต่สำหรับกรณีของเลขศูนย์และตัว ดูคำตอบทั่วไปมากขึ้นด้านล่าง (มีค่าใช้จ่ายที่มีประสิทธิภาพ)
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]])
>>>

ดูเช่นการทำดัชนีกับอาร์เรย์แบบบูล


3
ขอบคุณมากครับ หากคุณต้องการอ้างถึงค่าที่คุณเปลี่ยนแปลงคุณสามารถใช้สิ่งต่างๆเช่นa[a > 3] = -101+a[a > 3].
pexmar

1
@pexmar แม้ว่าคุณจะทำa[a > 3] = -101+a[a > 3]แทนคุณa[a > 3] += -101ส่วนใหญ่จะต้องเผชิญกับการรั่วไหลของหน่วยความจำ
Samuel Prevost

1
คุณอ้างอิงถึงค่าที่คุณเปลี่ยนแปลงตามที่ pexmar ถามได้อย่างไร ??
ฮวน

34

ที่เร็วที่สุด (และมีความยืดหยุ่นมากที่สุด) วิธีคือการใช้np.whereซึ่ง Chooses ระหว่างสองอาร์เรย์ตามหน้ากาก (อาร์เรย์ของค่าจริงและเท็จ):

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)

ซึ่งจะผลิต:

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
อะไรจะเป็นวิธีที่ดีที่สุดหากฉันไม่ต้องการแทนที่ด้วยสิ่งใดหากไม่ตรงตามเงื่อนไขคือแทนที่ด้วยค่าที่ระบุเมื่อตรงตามเงื่อนไขเท่านั้นหากไม่ปล่อยให้เป็นตัวเลขเดิมตามที่เป็นอยู่ ....
Abhishek Sengupta

1
เพื่อแทนที่ค่าทั้งหมดใน a ซึ่งมีค่าน้อยกว่า 3 และเก็บส่วนที่เหลือไว้ให้ใช้a[a<3] = 0
Markus Dutschke

3

คุณสามารถสร้างมาสก์อาร์เรย์ของคุณได้ในขั้นตอนเดียวเช่นนี้

mask_data = input_mask_data < 3

สิ่งนี้จะสร้างอาร์เรย์บูลีนซึ่งสามารถใช้เป็นมาสก์พิกเซลได้ โปรดทราบว่าเราไม่ได้เปลี่ยนอาร์เรย์อินพุต (เช่นเดียวกับในโค้ดของคุณ) แต่ได้สร้างอาร์เรย์ใหม่เพื่อเก็บข้อมูลมาสก์ - ฉันขอแนะนำให้ทำเช่นนี้

>>> 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
ใช่. ถ้า OP ต้องการ 0s และ 1s จริงๆเขาสามารถใช้.astype(int)หรือ*1แต่อาร์เรย์TrueและFalseดีพอ ๆ กัน
DSM

-4

ฉันไม่แน่ใจว่าฉันเข้าใจคำถามของคุณ แต่ถ้าคุณเขียน:

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

สิ่งนี้จะทำให้ค่าทั้งหมดของข้อมูลมาสก์ที่มีดัชนี x และ y น้อยกว่า 3 เท่ากับ 1 และส่วนที่เหลือทั้งหมดจะเท่ากับ 0

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.