Numpy - 两个一维数组的堆叠内存视图

5

我知道我可以做以下事情:

import numpy as np
c = np.random.randn(20, 2)
a = c[:, 0]
b = c[:, 1]

在这里,ab 是指向 c 的第一列和第二列的指针。修改 ab 将改变 c(反之亦然)。

然而,我想要实现的恰好相反。我想创建一个 2D 的内存视图,每一行(或列)将指向不同 1D 数组的内存。假设我已经有了两个 1D 数组,是否可以创建一个 2D 视图,其中每行/列指向它们中的一个?

我可以通过以下方式从 ab 创建 c

c = np.c_[a, b]

然而,这会将 ab 的内存复制到 c。我是否可以以某种方式创建 c 作为 [a b] 的“视图”,通过修改 c 中的元素来反映在相应的 ab 1D 数组中?

2个回答

5
我认为这是不可能的。
在你的第一个示例中,可以从以下变化中看到ab视图的值相互交织:
In [51]: c=np.arange(10).reshape(5,2)
In [52]: a, b = c[:,0], c[:,1]
In [53]: a
Out[53]: array([0, 2, 4, 6, 8])
In [54]: c.flatten()
Out[54]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

cadata缓冲区从同一内存点开始;b从该缓冲区的第4个字节开始。

In [55]: c.__array_interface__
Out[55]: 
{'strides': None,
 'data': (172552624, False),...}

In [56]: a.__array_interface__
Out[56]: 
{'strides': (8,),
 'data': (172552624, False),...}

In [57]: b.__array_interface__
Out[57]: 
{'strides': (8,),
 'data': (172552628, False),...}

即使将 a,b 拆分为行,b 也将在相同的共享数据缓冲区中进一步开始。
.flags 我们可以看出 c 是连续的,而 b 不是。但是,在该共享数据缓冲区中以恒定的步幅访问 b 值。
当独立创建 ab 时,它们的数据缓冲区完全是分开的。numpy 分层机制无法在这两个数据缓冲区之间来回移动。2d 的 ab 组合必须使用自己的数据缓冲区。
我可以想象编写一个看起来像你想要的类。定义 np.c_ 的 indexing_tricks 文件可能会给你带来灵感(例如,具有自定义 __getitem__ 方法的类)。但它不会拥有常规 2d 数组的速度优势。并且实现所有 ndarray 功能可能很难。

3

虽然@hpaulj的答案是正确的,但针对您的特定情况,更多地作为了解numpy内存布局的练习,而不是任何实际应用,下面是如何将两个1-D数组视为公共数组的列:

>>> from numpy.lib.stride_tricks import as_strided
>>> a = np.arange(10)
>>> b = np.arange(20, 30)
>>> col_stride = (b.__array_interface__['data'][0] -
                  a.__array_interface__['data'][0])
>>> c = as_strided(a, shape=(10, 2), strides=(a.strides[0], col_stride))
>>> c
array([[ 0, 20],
       [ 1, 21],
       [ 2, 22],
       [ 3, 23],
       [ 4, 24],
       [ 5, 25],
       [ 6, 26],
       [ 7, 27],
       [ 8, 28],
       [ 9, 29]])
>>> c[4, 1] = 0
>>> c[6, 0] = 0
>>> a
array([0, 1, 2, 3, 4, 5, 0, 7, 8, 9])
>>> b
array([20, 21, 22, 23,  0, 25, 26, 27, 28, 29])

这里有很多可能出错的事情,主要是数组b没有增加其引用计数,因此如果你删除它,它的内存将被释放,但视图仍将访问它。它也不能扩展到超过两个1-D数组,并且要求两个1-D数组具有相同的步幅。

当然,仅仅因为你可以做到并不意味着你应该这样做!你绝对不应该这样做。


感谢您的示例。我知道这不是理想的解决方案,但我认为它可以在“受控制”的环境下(例如课堂),当您可以确保'b'的存在时,它可能起作用。无论如何,再次感谢您们的解释。 - Imanol Luengo

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