Python - 重复numpy数组而不复制数据

8
这个问题之前已经有人问过,但解决方案只适用于一维/二维数组,我需要一个更通用的答案。
如何创建一个重复的数组而不复制数据?这对于向量化Python操作并避免内存消耗非常有用。
更具体地说,我有一个(y,x)数组,我想多次平铺它以创建一个(z,y,x)数组。我可以使用numpy.tile(array,(nz,1,1))来实现此目的,但我会耗尽内存。我的具体情况是x = 1500,y = 2000,z = 700。

1
你对更大的数组要做什么? array [None,:,:] 可能与平铺数组一样有用。除非在 y 或 x 维度上执行某种 点乘 操作,否则您仍可能遇到内存错误。 - hpaulj
我需要对一个地球物理数据集(时间,y,x)应用地理掩模。我使用的模块要求掩模与数据集具有相同的形状,这就是为什么我需要将(y,x)掩模复制到时间维度上的原因。 - user3644731
1个回答

5

一个简单的技巧是使用np.broadcast_arrays将你的(x, y)在第一维度上对一个长度为z的向量进行广播:

import numpy as np

M = np.arange(1500*2000).reshape(1500, 2000)
z = np.zeros(700)

# broadcasting over the first dimension
_, M_broadcast = np.broadcast_arrays(z[:, None, None], M[None, ...])

print M_broadcast.shape, M_broadcast.flags.owndata
# (700, 1500, 2000), False

为了将在这个回答中给出的针对1D数组的stride_tricks方法推广到多维数组,你只需要为输出数组的每个维度包括形状和步幅长度即可。
M_strided = np.lib.stride_tricks.as_strided(
                M,                              # input array
                (700, M.shape[0], M.shape[1]),  # output dimensions
                (0, M.strides[0], M.strides[1]) # stride length in bytes
            )

广播功能正好符合我的要求。在我看来,它比stride_tricks方法更简单/更合乎逻辑。 - user3644731
在内部,“broadcast_arrays” 正是以这种方式使用“as_strided”。请查看“numpy/lib/stride_tricks.py”。正是第一维的“0”步幅长度起了关键作用。 - hpaulj
stride length in bytes这一行应该改为(0, M.strides[0], M.strides[1]) - hpaulj
@hpaulj 这是一个有趣的知识点,尽管我相信直接使用 stride_tricks 仍然比分配另一个数组来进行广播更有效。 - ali_m
M[None,:,:] 的形状为 (1,...),步长为 (0,..)。新形状维度中的步长相同,但只有一个 1 - hpaulj
显示剩余2条评论

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