我有一个二维numpy
数组。有没有办法在它上面创建一个包含第一k
行和所有列的视图?
关键是要避免复制底层数据(数组太大以至于无法进行部分复制。)
当然,只需像往常一样索引它。例如y = x[:k, :]
,这会将视图返回到原始数组中。不会复制任何数据,所做的任何更新都y
将反映在x
其中,反之亦然。
编辑:
我通常使用大于 10GB 的 uint8 3D 数组,所以我很担心这个问题……如果你记住一些事情,Numpy 在内存管理方面会非常有效。以下是避免在内存中复制数组的一些技巧:
使用+=
, -=
,*=
等来避免复制数组。例如x += 10
,将就地修改数组,同时x = x + 10
复制并修改它。(另外,看看numexpr)
如果您确实想使用 制作副本,请x = x + 10
注意这x = x + 10.0
将导致x
自动向上转换为浮点数组(如果还没有的话)。但是,x += 10.0
, wherex
是一个整数数组,将导致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>)
将返回一个视图。
但是要小心……它非常强大和有用,但是您需要了解底层数据是如何存储在内存中的。如果您有一个浮点数组,并将它们视为整数,(反之亦然)numpy 会将数组的底层位解释为整数。
例如,这意味着1.0
在 little-endian 系统上的 64 位浮点数在被视为 64 位 int 时将被视为 64 位 int,而如果被视为 uint8 则为4607182418800017408
数组。[ 0, 0, 0, 0, 0, 0, 240, 63]
但是,当您需要对大型数组进行某种位旋转时,这非常好……您可以对内存缓冲区的解释方式进行低级控制。