numpy - 为什么 Z[(0,2)] 是视图而 Z[(0, 2), (0)] 是副本?
numpy - why Z[(0,2)] is view but Z[(0, 2), (0)] is copy?
问题
为什么 numpy 元组索引行为不一致?请解释这些行为背后的理性或设计决定。在我的理解中,Z[(0,2)]
和 Z[(0, 2), (0)]
都是 元组索引 并且期望 copy/view 的一致行为。如果不正确,请解释,
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,2),
(0)
]
print("Tuple indexing Z[(0, 2), (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, 2), (0)] is
[[ 0 1 2 3]
[24 25 26 27]]
Is view? False
Numpy 索引令人困惑,想知道人们是如何建立理解的。如果有好的理解方法或者备忘单,请指教
创建元组的是逗号。 () 只是在需要的地方设置边界。
因此
Z[(0,2)]
Z[0,2]
相同,select 在第一个 2 维上。 returns 是一个元素还是一个数组取决于 Z
有多少维度。
同样的解释适用于另一种情况。
Z[(0, 2), (0)]
Z[( np.array([0,2]), 0)]
Z[ np.array([0,2]), 0]
相同 - 第一个维度使用 list/array 进行索引,因此是高级索引。是副本。
[ 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, 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, False), # 38255712+8*8
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'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, False), # an entirely different location
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (2, 4),
'version': 3}
Z2
与两个 select 离子相同:
In [158]: Z[0,0]
Out[158]: array([0, 1, 2, 3])
In [159]: Z[2,0]
Out[159]: array([24, 25, 26, 27])
不是
Z[0][0][1] & Z[0][2][1]
Z[0,0,1] & Z[0,2,1]
将其与 2 行切片进行比较:
In [156]: Z3 = Z[0:2,0]
In [157]: Z3.__array_interface__
Out[157]:
{'data': (38255712, False), # same as Z's
'strides': (96, 8),
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (2, 4),
'version': 3}
如果新数组可以用shape
、strides
和原始数据缓冲区的全部或部分来描述,则返回一个视图。
问题
为什么 numpy 元组索引行为不一致?请解释这些行为背后的理性或设计决定。在我的理解中,Z[(0,2)]
和 Z[(0, 2), (0)]
都是 元组索引 并且期望 copy/view 的一致行为。如果不正确,请解释,
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,2),
(0)
]
print("Tuple indexing Z[(0, 2), (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, 2), (0)] is
[[ 0 1 2 3]
[24 25 26 27]]
Is view? False
Numpy 索引令人困惑,想知道人们是如何建立理解的。如果有好的理解方法或者备忘单,请指教
创建元组的是逗号。 () 只是在需要的地方设置边界。
因此
Z[(0,2)]
Z[0,2]
相同,select 在第一个 2 维上。 returns 是一个元素还是一个数组取决于 Z
有多少维度。
同样的解释适用于另一种情况。
Z[(0, 2), (0)]
Z[( np.array([0,2]), 0)]
Z[ np.array([0,2]), 0]
相同 - 第一个维度使用 list/array 进行索引,因此是高级索引。是副本。
[ 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, 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, False), # 38255712+8*8
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'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, False), # an entirely different location
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (2, 4),
'version': 3}
Z2
与两个 select 离子相同:
In [158]: Z[0,0]
Out[158]: array([0, 1, 2, 3])
In [159]: Z[2,0]
Out[159]: array([24, 25, 26, 27])
不是
Z[0][0][1] & Z[0][2][1]
Z[0,0,1] & Z[0,2,1]
将其与 2 行切片进行比较:
In [156]: Z3 = Z[0:2,0]
In [157]: Z3.__array_interface__
Out[157]:
{'data': (38255712, False), # same as Z's
'strides': (96, 8),
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (2, 4),
'version': 3}
如果新数组可以用shape
、strides
和原始数据缓冲区的全部或部分来描述,则返回一个视图。