如何删除numpy数组中的特定元素

Dan*_*sen 180 python arrays numpy

如何从numpy数组中删除一些特定元素?说我有

import numpy as np

a = np.array([1,2,3,4,5,6,7,8,9])
Run Code Online (Sandbox Code Playgroud)

然后我想删除3,4,7a.我所知道的是值(index=[2,3,6])的索引.

Lev*_*von 244

使用numpy.delete() - 返回一个数组,其子轴数组沿轴被删除

numpy.delete(a, index)
Run Code Online (Sandbox Code Playgroud)

针对您的具体问题:

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]`
Run Code Online (Sandbox Code Playgroud)

请注意,numpy.delete()返回一个新数组,因为数组标量是不可变的,类似于Python中的字符串,因此每次对其进行更改时,都会创建一个新对象.即,引用delete() 文档:

" 删除了obj指定的元素的arr 副本.注意删除不会就地发生 ......"

如果我发布的代码有输出,则它是运行代码的结果.

  • 这个答案有误导性.numpy.delete的第二个参数不是要删除的项的索引,而是要删除的实际项. (8认同)
  • @IngviGautsson你错了。确实需要删除项目的索引,而不是项目本身。 (4认同)
  • @IngviGautsson不,您的评论有误导性。这按预期工作。但是,numpy.delete()的文档确实指出“通常最好使用布尔掩码”。举一个例子。 (2认同)

小智 51

有一个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])
Run Code Online (Sandbox Code Playgroud)

  • 很高兴知道.我认为np.delete会慢一些,但是唉,1000个整数的时间表示删除速度快了x2. (7认同)
  • 这很棒,因为它对数组的 *values* 进行操作,而不必提供要删除的索引/索引。例如:`np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))` (3认同)
  • 问题说“我所知道的只是值的索引”。所以,这是关于**通过索引删除项目**,而不是通过它们的值删除 (2认同)

Dig*_*lex 33

Numpy数组是不可变的,这意味着您在技术上无法从中删除项目.但是,您可以构建一个没有您不想要的值的数组,如下所示:

b = np.delete(a, [2,3,6])
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,numpy数组是可变的.例如,这样:`a [0] = 1`就会修改`a`.但他们无法调整大小. (29认同)
  • 定义说它是不可变的,但是如果通过分配新值它让您修改,那么它如何不可变? (4认同)
  • +1 提到“不可变”。记住,numpy 数组不适合快速更改大小(添加/删除元素) (2认同)

Pra*_*dey 9

要按值删除:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))
Run Code Online (Sandbox Code Playgroud)

  • 从 numpy 1.19 开始,人们可以这样做:`np.delete(original_array,original_array==value)` https://numpy.org/doc/stable/reference/ generated/numpy.delete.html (2认同)

And*_*dyK 8

np.delete如果我们知道要删除的元素的索引,则使用是最快的方法。但是,为了完整起见,让我添加另一种使用在np.isin. 此方法允许我们通过直接指定元素或通过它们的索引来删除元素:

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

按索引删除

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]
Run Code Online (Sandbox Code Playgroud)

按元素删除(不要忘记重新创建原始文件,a因为它在上一行中被重写了):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]
Run Code Online (Sandbox Code Playgroud)


Gar*_*tty 6

不是一个笨拙的人,我拍了一下:

>>> 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])
Run Code Online (Sandbox Code Playgroud)

根据我的测试,这表现优于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
Run Code Online (Sandbox Code Playgroud)

这是一个非常显着的差异(与我期望的方向相反),任何人都知道为什么会出现这种情况?

更奇怪的是,传递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
Run Code Online (Sandbox Code Playgroud)

编辑:它似乎与数组的大小有关.使用大型阵列,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
Run Code Online (Sandbox Code Playgroud)

显然,这一切都是无关紧要的,因为你应该总是去清楚并避免重新发明轮子,但我发现它有点有趣,所以我想我会留在这里.

  • 小心你实际比较的东西!在第一次迭代中你有一个'a = delte_stuff(a)`,这使得每次迭代都会变小.当您使用inbuild函数时,您不会将值存储回a,这将保持原始大小!除此之外,你可以大大加快你的功能,当你创建一个`索引`的集合ouf并检查,是否删除一个项目.修复这两件事,我得到10k项目:你的函数每循环6.22毫秒,`numpy.delete`为4.48毫秒,这大致是你所期望的. (2认同)
  • 另外两个提示:代替`np.array(list(range(x)))`使用`np.arange(x)`,并且为了创建索引,你可以使用`np.s _ [:: 2]`. (2认同)

Lui*_*ira 6

如果您没有要删除的元素的索引,可以使用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])
Run Code Online (Sandbox Code Playgroud)