วิธีการลบองค์ประกอบเฉพาะในอาร์เรย์ numpy


212

ฉันจะลบองค์ประกอบเฉพาะบางอย่างออกจากอาร์เรย์ numpy ได้อย่างไร บอกว่าฉันมี

import numpy as np

a = np.array([1,2,3,4,5,6,7,8,9])

จากนั้นผมก็ต้องการที่จะลบจาก3,4,7 aสิ่งที่ฉันรู้คือดัชนีของค่า ( index=[2,3,6])

คำตอบ:


285

ใช้numpy.delete () - ส่งคืนอาร์เรย์ใหม่ที่มีอาร์เรย์ย่อยตามแนวแกนที่ถูกลบ

numpy.delete(a, index)

สำหรับคำถามเฉพาะของคุณ:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = [2, 3, 6]

new_a = np.delete(a, index)

print(new_a) #Prints `[1, 2, 5, 6, 8, 9]`

โปรดทราบว่าnumpy.delete()ส่งคืนอาร์เรย์ใหม่เนื่องจากสเกลาของอาเรย์นั้นไม่สามารถเปลี่ยนรูปได้เหมือนกับสตริงใน Python ดังนั้นทุกครั้งที่มีการเปลี่ยนแปลงจะมีการสร้างออบเจ็กต์ใหม่ นั่นคือเพื่ออ้างอิงdelete() เอกสาร :

" สำเนาของ arr ที่มีองค์ประกอบที่ระบุโดย obj ถูกลบโปรดทราบว่าการลบจะไม่เกิดขึ้นในสถานที่ ... "

หากรหัสที่ฉันโพสต์มีเอาท์พุทเป็นผลมาจากการเรียกใช้รหัส


1
@IngviGautsson เมื่อคุณทำการแก้ไขของคุณคุณยังเปลี่ยนค่าที่ถูกต้องสำหรับองค์ประกอบจาก 2, 3, 6, 3, 4, 7 หากคุณเรียกใช้รหัสตอนนี้คุณจะไม่ได้รับผลลัพธ์ที่ถูกต้องเหมือนกรณีเดิม "m roll back การแก้ไข
วิน

1
AttributeError: วัตถุ 'รายการ' ไม่มีแอตทริบิวต์ 'ลบ'
munmunbb

3
@IngviGautsson ไม่ความคิดเห็นของคุณทำให้เข้าใจผิด ทำงานได้ตามที่คาดไว้ อย่างไรก็ตามเอกสารของ numpy.delete () ไม่ทราบว่า "มักจะดีกว่าที่จะใช้หน้ากากบูลีน"; ตัวอย่างของที่ได้รับยัง
Biggsy

1
@Levon คุณสามารถเพิ่มตัวอย่างสำหรับ 2D ได้หรือไม่
MattS

7
@IngviGautsson คุณผิด ใช้ดัชนีของรายการที่จะลบไม่ใช่รายการเอง
Le Frite

64

มีฟังก์ชั่นในตัวเพื่อรองรับสิ่งนั้น

import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([3,4,7])
>>> c = np.setdiff1d(a,b)
>>> c
array([1, 2, 5, 6, 8, 9])

7
ดีแล้วที่รู้. ฉันคิดว่า np.delete จะช้าลง แต่อนิจจา timeit สำหรับจำนวนเต็ม 1,000 ตัวบอกว่า delete เป็น x2 เร็วขึ้น
wbg

1
สิ่งนี้ดีมากเพราะทำงานกับค่าของอาร์เรย์แทนที่จะต้องระบุดัชนี / ดัชนีที่คุณต้องการลบ ตัวอย่างเช่น:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

สิ่งนี้ยังเรียงลำดับผลลัพธ์ซึ่งอาจไม่ใช่สิ่งที่ต้องการ เป็นอย่างอื่นดีมาก
rayzinnz

คำถามบอกว่า "สิ่งที่ฉันรู้คือดัชนีค่า" ดังนั้นมันเกี่ยวกับการลบรายการโดยดัชนีของพวกเขาไม่ได้ลบออกด้วยค่าของพวกเขา
Sherzod

35

อาร์เรย์ Numpy นั้นไม่เปลี่ยนรูปซึ่งหมายความว่าคุณไม่สามารถลบรายการออกได้ในทางเทคนิค อย่างไรก็ตามคุณสามารถสร้างอาร์เรย์ใหม่โดยไม่มีค่าที่คุณไม่ต้องการเช่นนี้

b = np.delete(a, [2,3,6])

1
+1 สำหรับการกล่าวถึง 'ไม่เปลี่ยนรูป' มันเป็นสิ่งที่ดีที่จะจำได้ว่าอาร์เรย์ numpy จะไม่ดีสำหรับการเปลี่ยนแปลงอย่างรวดเร็วของขนาด (ผนวกองค์ประกอบ / ลบ)
eumiro

38
ในทางเทคนิคอาร์เรย์ที่มีจำนวนมากจะไม่แน่นอน ตัวอย่างเช่นสิ่งนี้: a[0]=1แก้ไขaในสถานที่ แต่พวกเขาไม่สามารถปรับขนาด
btel

3
คำจำกัดความระบุว่ามันไม่เปลี่ยนรูป แต่ถ้ากำหนดค่าใหม่จะทำให้คุณปรับเปลี่ยนได้
JSR

16

หากต้องการลบตามค่า:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))

คำถามคือเกี่ยวกับการลบรายการด้วยดัชนีไม่ใช่การลบรายการที่มีค่าเฉพาะ
Sherzod

5

ฉันไม่ได้เป็นคนขี้แพ้

>>> import numpy as np
>>> import itertools
>>> 
>>> a = np.array([1,2,3,4,5,6,7,8,9])
>>> index=[2,3,6]
>>> a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))
>>> a
array([1, 2, 5, 6, 8, 9])

จากการทดสอบของฉันมีประสิทธิภาพดีกว่าnumpy.delete()นี้ ฉันไม่รู้ว่าทำไมเป็นเช่นนั้นอาจเป็นเพราะอาร์เรย์ขนาดเล็กเริ่มต้นใช่ไหม

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
100000 loops, best of 3: 12.9 usec per loop

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "np.delete(a, index)"
10000 loops, best of 3: 108 usec per loop

นั่นคือความแตกต่างอย่างมีนัยสำคัญ (ในทิศทางตรงกันข้ามกับสิ่งที่ฉันคาดหวัง) ทุกคนมีความคิดว่าทำไมถึงเป็นเช่นนั้น?

ยิ่งแปลกกว่านั้นการผ่านnumpy.delete()รายการมีประสิทธิภาพแย่กว่าการวนลูปผ่านรายการและให้ดัชนีเดียว

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "for i in index:" "    np.delete(a, i)"
10000 loops, best of 3: 33.8 usec per loop

แก้ไข: ดูเหมือนว่าจะทำอย่างไรกับขนาดของอาร์เรย์ ด้วยอาร์เรย์ขนาดใหญ่numpy.delete()จะเร็วกว่ามาก

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
10 loops, best of 3: 200 msec per loop

python -m timeit -s "import numpy as np" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "np.delete(a, index)"
1000 loops, best of 3: 1.68 msec per loop

เห็นได้ชัดว่านี่เป็นสิ่งที่ไม่เกี่ยวข้องอย่างที่ควรจะเป็นเพื่อความชัดเจนและหลีกเลี่ยงการสร้างล้อใหม่ แต่ฉันคิดว่ามันน่าสนใจเล็กน้อยดังนั้นฉันคิดว่าฉันจะทิ้งมันไว้ที่นี่


2
ระวังสิ่งที่คุณเปรียบเทียบจริง ๆ ! คุณมีa = delte_stuff(a)ในการทำซ้ำครั้งแรกของคุณซึ่งทำให้aเล็กลงสำหรับการทำซ้ำทุกครั้ง เมื่อคุณใช้ฟังก์ชั่น inbuild คุณจะไม่เก็บค่ากลับเป็น a ซึ่งเก็บ a ในขนาดดั้งเดิม! นอกจากนั้นคุณสามารถเร่งความเร็วฟังก์ชั่นของคุณอย่างมากเมื่อคุณสร้างชุดของindexและตรวจสอบว่าจะลบรายการหรือไม่ แก้ไขทั้งสองอย่างฉันได้ไอเท็ม 10k: 6.22 msec ต่อลูปพร้อมกับฟังก์ชั่นของคุณ 4.48 msec สำหรับnumpy.deleteซึ่งเป็นสิ่งที่คุณคาดหวัง
Michael

2
สองคำแนะนำเพิ่มเติมได้ที่: แทนการnp.array(list(range(x)))ใช้งานและการสร้างดัชนีคุณสามารถใช้np.arange(x) np.s_[::2]
Michael

1

หากคุณไม่รู้จักดัชนีคุณไม่สามารถใช้งานได้ logical_and

x = 10*np.random.randn(1,100)
low = 5
high = 27
x[0,np.logical_and(x[0,:]>low,x[0,:]<high)]

1

การใช้ np.deleteเป็นวิธีที่เร็วที่สุดในการทำหากเรารู้ดัชนีขององค์ประกอบที่เราต้องการลบ อย่างไรก็ตามเพื่อความสมบูรณ์ให้ฉันเพิ่มวิธีการ "ถอด" np.isinองค์ประกอบมากมายโดยใช้หน้ากากแบบบูลที่สร้างขึ้นด้วยความช่วยเหลือของอีก วิธีนี้ช่วยให้เราสามารถลบองค์ประกอบโดยระบุพวกเขาโดยตรงหรือดัชนีของพวกเขา:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

ลบตามดัชนี :

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]

ลบตามองค์ประกอบ (อย่าลืมสร้างต้นฉบับใหม่aเนื่องจากเขียนใหม่ในบรรทัดก่อนหน้า):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]

0

ลบดัชนีเฉพาะ (ฉันลบ 16 และ 21 ออกจากเมทริกซ์)

import numpy as np
mat = np.arange(12,26)
a = [4,9]
del_map = np.delete(mat, a)
del_map.reshape(3,4)

เอาท์พุท:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])

0

คุณยังสามารถใช้ชุด:

a = numpy.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
the_index_list = [2, 3, 6]

the_big_set = set(numpy.arange(len(a)))
the_small_set = set(the_index_list)
the_delta_row_list = list(the_big_set - the_small_set)

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