微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

numpy - 为什么 Z[(0,2)] 是视图而 Z[(0, 2), (0)] 是副本?

如何解决numpy - 为什么 Z[(0,2)] 是视图而 Z[(0, 2), (0)] 是副本?

问题

为什么 numpy 元组索引行为不一致?请解释这些行为背后的理性或设计决策。根据我的理解,Z[(0,2)]Z[(0,2),(0)] 都是 元组索引,并且期望复制/查看的行为一致。如果不正确,请解释,

import numpy as np
Z = np.arange(36).reshape(3,3,4)
print("Z is \n{}\n".format(Z))

b =  Z[
    (0,2)      # Select Z[0][2]
]
print("Tuple indexing Z[(0,2)] is \n{}\nIs view? {}\n".format(
    b,b.base is not None
))

c = Z[         # Select Z[0][0][1] & Z[0][2][1]
    (0,(0)
]
print("Tuple indexing Z[(0,(0)] is \n{}\nIs view? {}\n".format(
    c,c.base is not None
))
Z is 
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]

 [[24 25 26 27]
  [28 29 30 31]
  [32 33 34 35]]]

Tuple indexing Z[(0,2)] is 
[ 8  9 10 11]
Is view? True

Tuple indexing Z[(0,(0)] is 
[[ 0  1  2  3]
 [24 25 26 27]]
Is view? False

Numpy 索引令人困惑,不知道人们是如何建立理解的。如果有好的理解方法或备忘单,请指教。

解决方法

它是创建元组的逗号。 () 只是在需要的地方设置边界。

因此

Z[(0,2)]
Z[0,2]

相同,在第一个二维上选择。返回的是元素还是数组取决于 Z 有多少维。

同样的解释适用于另一种情况。

Z[(0,2),(0)]
Z[( np.array([0,2]),0)]
Z[ np.array([0,0]

是相同的 - 第一个维度使用列表/数组进行索引,因此是高级索引。这是一个副本。

[ 8  9 10 11]

是 3d 数组的一行;它是一个连续的 Z

[[ 0  1  2  3]
 [24 25 26 27]]

Z 的 2 行。它们不是连续的,因此无法仅通过形状和步幅(以及数据缓冲区中的偏移量)来识别它们。

详情

__array_interface__ 提供有关数组底层数据的详细信息

In [146]: Z = np.arange(36).reshape(3,3,4)
In [147]: Z.__array_interface__
Out[147]: 
{'data': (38255712,False),'strides': None,'descr': [('','<i8')],'typestr': '<i8','shape': (3,4),'version': 3}
In [148]: Z.strides
Out[148]: (96,32,8)

对于视图:

In [149]: Z1 = Z[0,2]
In [150]: Z1
Out[150]: array([ 8,9,10,11])
In [151]: Z1.__array_interface__
Out[151]: 
{'data': (38255776,# 38255712+8*8
 'strides': None,'shape': (4,),'version': 3}

数据缓冲区指针是 Z 缓冲区中更远的 8 个元素。形状大大缩小。

In [152]: Z2 = Z[[0,2],0]
In [153]: Z2
Out[153]: 
array([[ 0,1,2,3],[24,25,26,27]])
In [154]: Z2.__array_interface__
Out[154]: 
{'data': (31443104,# an entirely different location
 'strides': None,'shape': (2,'version': 3}

Z2 与两个选择相同:

In [158]: Z[0,0]
Out[158]: array([0,3])
In [159]: Z[2,0]
Out[159]: array([24,27])

不是

Z[0][0][1] & Z[0][2][1]
Z[0,1] & Z[0,1]

将其与 2 行切片进行比较:

In [156]: Z3 = Z[0:2,0]
In [157]: Z3.__array_interface__
Out[157]: 
{'data': (38255712,# same as Z's
 'strides': (96,8),'version': 3}

如果新数组可以用 shapestrides 和全部或部分原始数据缓冲区来描述,则返回一个视图。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。