【问题标题】:How to remove specific elements in a numpy array如何删除numpy数组中的特定元素
【发布时间】:2012-06-15 07:18:42
【问题描述】:

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

import numpy as np

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

然后我想从a 中删除3,4,7。我只知道值的索引 (index=[2,3,6])。

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    过滤掉不需要的部分:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        列表理解也是一种有趣的方法。

        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]
        

        【讨论】:

          【解决方案4】:

          如果我们知道要删除的元素的索引,使用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)]
          

          【讨论】:

            【解决方案5】:

            你也可以使用集合:

            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]
            

            【讨论】:

              【解决方案6】:

              删除特定索引(我从矩阵中删除了 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]])
              

              【讨论】:

                【解决方案7】:

                按值删除:

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

                【讨论】:

                • 问题是关于按索引删除项目,而不是删除具有特定值的项目
                【解决方案8】:

                不知道索引就不能用logical_and

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

                【讨论】:

                  【解决方案9】:

                  使用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() 返回一个新数组,因为array scalars 是不可变的,类似于 Python 中的字符串,因此每次对其进行更改时,都会创建一个新对象。即,引用delete() docs

                  "a copy arr 删除了 obj 指定的元素。请注意 删除不会就地发生..."

                  如果我发布的代码有输出,那是代码运行的结果。

                  【讨论】:

                  • @IngviGautsson 当您进行编辑时,您还将元素的正确值从 2、3、6 更改为 3、4、7,如果您现在运行代码,您不会得到正确的输出原样。我正在回滚编辑
                  • AttributeError: 'list' 对象没有属性 'delete'
                  • @IngviGautsson 不,您的评论具有误导性。这按预期工作。但是, numpy.delete() 的文档确实指出“通常最好使用布尔掩码”;也给出了一个例子。
                  • @Levon 你可以为 2D 添加示例吗?
                  • @IngviGautsson 你错了。它确实需要删除项目的索引,而不是项目本身。
                  【解决方案10】:

                  有一个 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])
                  

                  【讨论】:

                  • 很高兴知道。我在想 np.delete 会慢一些,但可惜的是,1000 个整数的 timeit 说 delete 快 x2。
                  • 这很棒,因为它对数组的 进行操作,而不必提供要删除的索引/索引。例如:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
                  • 这也会对输出进行排序,这可能不是我们想要的。否则非常好。
                  • 问题是“我所知道的只是值的索引”。所以,这是关于按索引删除项目,而不是按其值删除
                  【解决方案11】:

                  我不是一个麻木的人,我拍了一张照片:

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

                  显然,这一切都无关紧要,因为您应该始终保持清晰并避免重新发明轮子,但我发现它有点有趣,所以我想我会把它留在这里。

                  【讨论】:

                  • 小心你实际比较的东西!您在第一次迭代中有a = delte_stuff(a),这使得a 在每次迭代中都变小了。当您使用 inbuild 函数时,您不会将值存储回 a,这会使 a 保持原始大小!除此之外,当您创建一组 index 并检查是否删除项目时,您可以大大加快您的功能。解决这两个问题,我得到了 10k 个项目:使用您的函数每个循环 6.22 毫秒,numpy.delete 为 4.48 毫秒,这大致是您所期望的。
                  • 另外两个提示:不要使用np.array(list(range(x))),而是使用np.arange(x),对于创建索引,您可以使用np.s_[::2]
                  【解决方案12】:

                  Numpy 数组是immutable,这意味着从技术上讲,您不能从中删除项目。但是,您可以构造一个 new 数组而不包含您不想要的值,如下所示:

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

                  【讨论】:

                  • +1 用于提及“不可变”。记住,numpy 数组不适合快速更改大小(追加/删除元素)
                  • 从技术上讲,numpy 数组是可变的。例如,这个:a[0]=1 就地修改了a。但它们不能调整大小。
                  • 定义说它是不可变的,但是如果通过分配新的值让你修改,那么它怎么不可变呢?
                  猜你喜欢
                  • 2019-11-15
                  • 2022-01-21
                  • 2019-07-16
                  • 2016-01-25
                  • 1970-01-01
                  • 2016-11-11
                  • 2019-11-28
                  • 1970-01-01
                  相关资源
                  最近更新 更多