查看到一个numpy数组?


90

我有一个二维numpy数组。有没有一种方法可以在其上创建一个包含第一k行和所有列的视图?

关键是要避免复制基础数据(数组太大,无法进行部分复制)。

Answers:


226

当然,只需像平常一样对它编制索引即可。例如,y = x[:k, :] 这将使视图返回原始数组。不会复制任何数据,对其所做的任何更新都y将反映在其中x,反之亦然。


编辑:

我通常使用uint8的大于10GB的3D阵列,因此我对此非常担心...如果记住一些事项,Numpy可以非常有效地进行内存管理。这里有一些避免在内存中复制数组的技巧:

使用+=-=*=等,以避免使数组的一个副本。例如,x += 10将在适当位置修改数组,同时x = x + 10将复制并修改它。(另外,看看numexpr

如果您确实想使用进行复制x = x + 10,请注意,这x = x + 10.0将导致x将其自动转换为浮点数组(如果尚未复制)。但是,x += 10.0在哪里,x是整数10.0数组,而是将向下转换为与数组精度相同的int。

此外,许多numpy函数都带有一个out参数,因此您可以执行一些操作np.abs(x, x)来获取x就地的绝对值。


作为第二个编辑,这是有关视图和具有numpy数组的副本的更多技巧:

与python列表不同,y = x[:]它不返回副本,而是返回视图。如果您确实想要一个副本(当然,它将使您正在使用的内存量增加一倍),请使用y = x.copy()

您会经常听到有关numpy数组的“花式索引”的信息。使用列表(或整数数组)作为索引是“花式索引”。它可能非常有用,但是可以复制数据。

例如:y = x[[0, 1, 2], :]返回一个副本,而y = x[:3,:]返回一个视图。

即使是真正疯狂的索引,也x[4:100:5, :-10:-1, None]都是“正常”索引,并且会返回一个视图,因此,不要害怕在大型数组上使用各种切片技巧。

x.astype(<dtype>)将以新类型x.view(<dtype>)返回数据的副本,而将返回视图。

但是,请务必小心……它非常强大且有用,但是您需要了解底层数据如何存储在内存中。如果您有一个浮点数组,并且将它们视为int,则numpy会将数组的基础解释为int。

例如,这意味着当被视为64位int时,1.0在little-endian系统上为64位浮点数4607182418800017408[ 0, 0, 0, 0, 0, 0, 240, 63]如果被视为uint8 ,则将为数组。但是,当您需要在大型阵列上进行某种形式的位纠缠时,这确实非常好。您可以对内存缓冲区的解释方式进行低级控制。


感谢非常好的提示!我正在阅读Numpy用户指南,并对为什么要x[np.array([1, 1, 3, 1])] += 1修改感到困惑x。现在知道了!
tnq177

不错的提示!我有另一个问题。如何证明numpy不会触发副本而是触发视图?python的id()似乎无能为力。
wuhaochi

3
@wuhaochi如果b是这样的a话,b.base is a将会是True。(任何数组)的副本将总是有arr_copy.base is None
尔格默林斯巴克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.