根据numpy documentation的说法,高级索引应该返回数组的副本.这在一维的情况下如预期的那样工作.但是,如果数组是多维的,则Numpy不会将其识别为副本.如果我没有访问原始数组的权限,我如何测试在多维情况下是否返回副本或视图?

例如:

import numpy as np

y = np.ones((1, 10))
b = y[:, [0, 5, 6]]

# b is not a copy
assert not b.flags['OWNDATA']
assert b.base is not None

但它实际上是一份复制品

b[:] = 33
print(y)

推荐答案

让我们把y变得更有趣一点:

In [915]: y = np.arange(10).reshape(2,5);y, y.base
Out[915]: 
(array([[0, 1, 2, 3, 4],
        [5, 6, 7, 8, 9]]),
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))

它是一维数组中的view个.

现在使用高级索引:

In [916]: b = y[:,[0,2,4]];b, b.base
Out[916]: 
(array([[0, 2, 4],
        [5, 7, 9]]),
 array([[0, 5],
        [2, 7],
        [4, 9]]))

In [917]: b.strides, b.base.strides
Out[917]: ((4, 8), (8, 4))

正如我们从索引中预期的那样,b是一个(2,3)数组,但它实际上是一个(3,2)数组的转置.显然,numpy正在使用列表索引(第二维) Select 值,并将切片维度放在最后.然后,它会转置以获得所需的形状.这暗示了为什么混合高级索引和基本索引可能会产生意外的形状(如其他SO中所述和文档所述).

在任何情况下,我都找不到一种方法来测试b来验证它不是yview--除非通过比较base个属性.最简单的事情就是接受文档所声称的它是副本--只是不是"直接"副本.

我们可以使用基本索引得到相同的数组--得到的是view,即y.base:

In [918]: c = y[:,::2]; c, c.base
Out[918]: 
(array([[0, 2, 4],
        [5, 7, 9]]),
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))

还有其他几种获得简单副本的方法:

In [924]: d = y[[0,1], ::2]; d, d.base
Out[924]: 
(array([[0, 2, 4],
        [5, 7, 9]]),
 None)

In [925]: d = y[[[0],[1]], [0,2,4]]; d, d.base
Out[925]: 
(array([[0, 2, 4],
        [5, 7, 9]]),
 None)

Python相关问答推荐

我在使用fill_between()将最大和最小带应用到我的图表中时遇到问题

由于NEP 50,向uint 8添加-256的代码是否会在numpy 2中失败?

Matlab中是否有Python的f-字符串等效物

处理带有间隙(空)的duckDB上的重复副本并有效填充它们

更改键盘按钮进入'

基于字符串匹配条件合并两个帧

ThreadPoolExecutor和单个线程的超时

CommandeError:模块numba没有属性generated_jit''''

Tkinter菜单自发添加额外项目

使用特定值作为引用替换数据框行上的值

剪切间隔以添加特定日期

ConversationalRetrivalChain引发键错误

在Docker容器(Alpine)上运行的Python应用程序中读取. accdb数据库

Python 3试图访问在线程调用中实例化的类的对象

Seaborn散点图使用多个不同的标记而不是点

如何关联来自两个Pandas DataFrame列的列表项?

如何在Quarto中的标题页之前创建序言页

在使用ROLING()获得最大值时,是否可以排除每个窗口中的前n个值?

Pandas ,快速从词典栏中提取信息到新栏

Python:使用asyncio.StreamReader.readline()读取长行