numpy:如果 numpy 数组是视图,则可靠(非保守)指示符

Posted

技术标签:

【中文标题】numpy:如果 numpy 数组是视图,则可靠(非保守)指示符【英文标题】:numpy: Reliable (non-conservative) indicator if numpy array is view 【发布时间】:2016-02-05 11:20:48 【问题描述】:

寻找一种方法来可靠地识别 numpy 对象是否是视图。

相关问题之前出现过很多次(here、here、here),也有人提出了一些解决方案,但似乎都有问题:

现在pandas 中使用的测试是在my_array.base is not None 中调用某个视图。这似乎总能捕获视图,但也提供了许多误报(它报告某些内容的情况是视图,即使它不是视图)。 numpy.may_share_memory() 将检查两个特定数组,但一般不会回答 (@RobertKurn 说它是 2012 年最好的工具——有什么变化吗?) flags['OWNDATA']) 是 reported (third comment first answer) 在某些情况下会失败。

(我感兴趣的原因是我正在为 pandas 实现写时复制,保守的指标导致过度复制。)

【问题讨论】:

关于numpy github tracker的相关讨论:github.com/numpy/numpy/issues/5604 被描述为误报的情况似乎是“创建副本”的操作实际上返回副本的视图。如果这被认为是“不是视图”,您可以尝试检查数组的 base 的引用计数,以查看是否有其他对它的引用,但这并不完美。我认为不可能可靠地检测到这种事情。 另见这个最近的 SO 问题,***.com/questions/33467477/…。它提到了一个新功能,np.shares_memory。但我强调,比较 2 个已知变量是一回事,另一个要问的是数组与任何其他数组共享数据缓冲区。 一个 numpy 数组和稍后创建的视图怎么样,你想如何处理原始数组? 就我而言,原件可以视为“不是视图”。 【参考方案1】:

根据您的使用情况,flags['OWNDATA'] 可以完成这项工作。 实际上,您的链接没有问题。 在某些情况下它不会失败。它总是会做它应该做的事情。

根据http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.require.html:标志“确保数组拥有自己的数据”。

在您的“反例”中,他们使用代码:

print (b.flags['OWNDATA'])  #False -- apparently this is a view
e = np.ravel(b[:, 2])
print (e.flags['OWNDATA'])  #True -- Apparently this is a new numpy object.

但是,在第二种情况下为 True 是正常行为。

它来自ravel的定义(来自http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.ravel.html)。

返回一个连续的扁平数组。 返回一个包含输入元素的一维数组。仅在需要时才制作副本。

这里需要一个副本,所以制作了一个副本。因此,变量 e 真正拥有自己的数据。它不是“b 的视图”、“b 的引用”、“b 的一部分的别名”。这是一个真正的新数组,包含 b 的一些元素的副本。

所以,我认为如果不跟踪数据的整个来源来检测这种行为是不可能的。我相信您应该能够使用该标志构建您的程序。

【讨论】:

以上是关于numpy:如果 numpy 数组是视图,则可靠(非保守)指示符的主要内容,如果未能解决你的问题,请参考以下文章

python使用numpy的array_equal函数判断两个numpy数组是否具有相同的形状(shape)和元素(elements)如果都满足则返回True否则返回False

如果满足条件,则替换 Numpy 元素

Numpy | 20 副本和视图

Python Numpy数组的读入存储操作

如果条件不满足,则保留最后一个值的 if/elif/else 的 Numpy 等效项

numpy矩阵和数组的区别