【问题标题】:Efficient way to drop a column from a Numpy array?从 Numpy 数组中删除列的有效方法?
【发布时间】:2014-01-02 01:32:40
【问题描述】:

如果我有一个非常大的 numpy 数组,其中包含一个无用的列,我怎么能在不创建原始数组的副本的情况下删除它

np.delete(my_np_array, 0, 1)

上面的代码将返回没有第零列的数组副本。但相反,我想简单地从my_np_array 中删除该列,因为我不需要它。对于非常大的数据集,内存管理变得很重要,复制可能不是一种选择。

【问题讨论】:

  • 不幸的是,在 numpy 中防止复制是一件棘手的事情。如果它是第一列或最后一列,您可能可以使用简单的数组切片。这可能不会现在复制数组,但是如果你继续用它做更复杂的事情,不能保证你以后不会得到副本(或临时数组)代码(AFAIK)。
  • @Krishan 是否可以将它以不同的方式加载到 python 中?如果数组是从数据中生成的,我们可以做一些事情来事先杀死列吗?如果没有,我们可以用其他方式预处理数组吗,比如MATLAB

标签: python arrays numpy slice


【解决方案1】:

如果内存是主要问题,您可以做的是在数组中移动列,以使不需要的列位于数组的最后,然后使用ndarray.resize,它会就地修改数组,以将其缩小并丢弃外列。

您不能简单地使用提供的 API 就地删除数组的第一列,我怀疑这是因为 memory layout of an ndarray 将多维索引映射到连续内存块内的一维面向字节的寻址。

以下示例将最后一列复制到第一列,然后删除最后一列(现在不需要),立即清除关联的内存。所以它基本上从内存中完全删除了过时的列,代价是改变你的列顺序。

D1, D2 = A.shape
A[:, 0] = A[:, D2-1] 
A.resize((D1, D2-1), refcheck=False)
A.shape  
# => would be (5, 4) if the shape was initially (5, 5) for example

【讨论】:

    【解决方案2】:

    Numpy 数组是不可变的。因此,如果不创建中间副本,就无法调整它们的大小。 How to remove specific elements in a numpy array 使用切片创建视图并制作副本可能是您能做到的最快速度。

    In [804]: a = np.ones((2,2))
    
    In [805]: a
    Out[805]:
    array([[ 1.,  1.],
           [ 1.,  1.]])
    
    In [806]: np.resize(a,(3,2))
    Out[806]:
    array([[ 1.,  1.],
           [ 1.,  1.],
           [ 1.,  1.]])
    
    In [807]: a  <- a should now be resized if it was done inplace? 
    Out[807]:
    array([[ 1.,  1.],
           [ 1.,  1.]])
    

    【讨论】:

    • 根据ndarray.resize's documentation,可以就地修改数组。
    • np.resize 返回一个新数组,a.resize(其中a 是一个数组)就地调整其大小
    【解决方案3】:

    如果你使用切片numpy 不会复制;换句话说

    a = numpy.array([1, 2, 3, 4, 5])
    b = a[1:]  # view elements from second to last, NOT making a copy
    b[0] = 12  # Change first element of `b`, i.e. second of `a`
    print a
    

    会回复[1, 12, 3, 4, 5]

    如果您需要删除中间的一个元素,但是单个切片将不起作用。

    【讨论】:

    • 只是添加...对于 OP 案例做 b=a[:,1:]
    • 我很想知道,因为当您使用切片时,numpy 为您提供了相同数据结构的新“视图”,它何时真正“释放”内部某个列使用的内存它?换句话说,它是依赖 Python 的 GC 还是什么?你的解决方案基本上告诉 numpy 你现在需要一个相同数据的新视图,你还没有告诉它它可以丢弃它的一部分。如果 OP 关心的是尽快释放一部分不需要的内存,我想知道什么时候会发生。
    • @matehat 内存释放不会发生,因为视图只是一种访问为数组分配的内存以不同方式分配的方法(转换为其他类型,重新整形/广播为不同的形状,跳过某些列/行等),并且只能完全释放,不能部分释放
    猜你喜欢
    • 2014-10-04
    • 1970-01-01
    • 2019-08-04
    • 2012-12-14
    • 2019-09-19
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多