簡體   English   中英

如何刪除 numpy 數組中的特定元素

[英]How to remove specific elements in a numpy array

如何從 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] )。

使用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() 文檔

刪除了 obj 指定的元素的 arr副本請注意,刪除不會就地發生......”

如果我貼的代碼有輸出,就是運行代碼的結果。

有一個 numpy 內置函數可以幫助解決這個問題。

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

Numpy 數組是不可變的,這意味着您在技術上無法從中刪除項目。 但是,您可以構造一個沒有不需要的值的數組,如下所示:

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

按值刪除:

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

如果我們知道要刪除的元素的索引,則使用np.delete是最快的方法。 但是,為了完整np.isin ,讓我添加另一種使用在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)]

不是一個麻木的人,我拍了一張:

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

顯然,這一切都無關緊要,因為您應該始終保持清晰並避免重新發明輪子,但我覺得它有點有趣,所以我想我會把它留在這里。

如果不知道索引,就不能使用logical_and

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

列表理解也可能是一種有趣的方法。

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = np.array([2, 3, 6]) #index is changed to an array.  
out = [val for i, val in enumerate(a) if all(i != index)]
>>> [1, 2, 5, 6, 8, 9]

刪除特定索引(我從矩陣中刪除了 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]])

您還可以使用集合:

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]

如果您沒有要刪除的元素的索引,則可以使用 numpy 提供的函數in1d

如果一維數組的元素也存在於第二個數組中,則該函數返回True 要刪除元素,您只需否定此函數返回的值。

請注意,此方法保持原始數組的順序

In [1]: import numpy as np

        a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
        rm = np.array([3, 4, 7])
        # np.in1d return true if the element of `a` is in `rm`
        idx = np.in1d(a, rm)
        idx

Out[1]: array([False, False,  True,  True, False, False,  True, False, False])

In [2]: # Since we want the opposite of what `in1d` gives us, 
        # you just have to negate the returned value
        a[~idx]

Out[2]: array([1, 2, 5, 6, 8, 9])

如果你現在不知道索引,你可以這樣做:

arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
values = [3, 4, 7]
mask = np.isin(arr, values)
arr = np.delete(arr, mask)

這種帶掩碼的語法是在 1.19 中引入的

過濾不需要的部分:

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

如果您有要刪除的索引列表:

to_be_removed_inds = [2,3,6]
a = np.array([1,2,3,4,5,6,7,8,9])
a = a[[x for x in range(len(a)) if x not in to_be_removed]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM