从Numpy数组中删除列的有效方法是什么?

9
如果我有一个非常大的numpy数组,其中有一列是无用的,那么如何在不创建原始数组的副本的情况下删除它?
np.delete(my_np_array, 0, 1)

上面的代码将返回一个去掉第零列的数组副本。但是我想要从 my_np_array 中直接删除该列,因为我不需要它。对于非常大的数据集,内存管理变得很重要,复制可能不是一个选项。

2
在numpy中防止复制是非常棘手的。 如果是第一列或最后一列,您可能可以使用简单的数组切片来避免复制。 可能现在不会复制数组,但是如果您继续对其进行更复杂的操作,则无法保证您不会在代码中稍后获得副本(或临时数组)(据我所知)。 - mgilson
@Krishan 能否以不同方式将其加载到Python中?如果数组是从数据中生成的,我们能否在手头执行某些操作删除该列?如果不行,我们是否可以通过其他方式预处理该数组,例如使用MATLAB - Ray
3个回答

5
如果内存是主要问题,您可以在数组内部移动列,使不需要的列位于数组的最后,然后使用 ndarray.resize,该函数会直接在原地修改数组大小并丢弃外部列。
您无法直接使用提供的API在原地删除数组的第一列,我怀疑这是由于 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

4
如果您使用切片,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]

如果您需要删除中间的元素,但单个切片无法实现。


1
仅为OP案例添加...,执行 b=a[:,1:] - Saullo G. P. Castro
我很好奇,由于numpy在使用切片时会为您提供相同数据结构的新“视图”,那么它实际上何时才会释放其中某列使用的内存?换句话说,它是否依赖于Python的GC或其他什么东西?您的解决方案基本上告诉numpy,您现在需要相同数据的新视图,但还没有告诉它可以丢弃一部分。如果OP的关注点是尽快释放一些不需要的内存,我想知道什么时候会发生这种情况。 - matehat
1
@matehat 内存释放不会发生,因为视图仅是访问为数组分配的内存的方法(以其他类型转换,重新整形/广播到不同的形状,跳过某些列/行等),只能完全释放,而不能部分释放。 - alko

0
Numpy数组是不可变的。因此,如果要重新调整大小,就必须创建一个中间副本。 如何从numpy数组中删除特定元素 使用切片创建视图,并复制它可能是最快的方法。
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的文档,数组可以就地修改。 - matehat
np.resize可以返回一个新的数组,而a.resize(其中a是一个数组)可以原地调整其大小。 - matehat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接