Python numpy,对ndarray.base的理解
我尝试了以下实验,以了解使用二维数组的numpy中的视图和副本 正如我们在下面看到的,切片创建了一个视图(a),使用整数列表进行索引创建了一个副本(c.base与arr不同,d.base为None)。根据我的理解,这是预期的行为 我不明白的是为什么c.base不是None,为什么c.flags.owndata是False。如果这是一个新的副本,为什么会发生这种情况 我注意到d视图的情况并非如此Python numpy,对ndarray.base的理解,python,arrays,numpy,Python,Arrays,Numpy,我尝试了以下实验,以了解使用二维数组的numpy中的视图和副本 正如我们在下面看到的,切片创建了一个视图(a),使用整数列表进行索引创建了一个副本(c.base与arr不同,d.base为None)。根据我的理解,这是预期的行为 我不明白的是为什么c.base不是None,为什么c.flags.owndata是False。如果这是一个新的副本,为什么会发生这种情况 我注意到d视图的情况并非如此 import numpy as np arr = np.array([[1,2,4,8],
import numpy as np
arr = np.array([[1,2,4,8],
[16, 32, 64, 128],
[256, 512, 1024, 2048]])
print(arr)
print(arr.base)
print(arr.flags.owndata)
# [[ 1 2 4 8]
# [ 16 32 64 128]
# [ 256 512 1024 2048]]
# None
# True
# this is a view, identical base to arr.base
a = arr[:,1:3]
print(a)
print(a.base)
print(np.shares_memory(a, arr))
print(a.flags.owndata)
# [[ 2 4]
# [ 32 64]
# [ 512 1024]]
# [[ 1 2 4 8]
# [ 16 32 64 128]
# [ 256 512 1024 2048]]
# True
# False
# this is a copy, its own base, does not share memory with arr
c = arr[:,[1,3]]
print(c)
print(c.base)
print(np.shares_memory(c, arr))
print(c.flags.owndata)
# [[ 2 8]
# [ 32 128]
# [ 512 2048]]
# [[ 2 32 512]
# [ 8 128 2048]]
# False
# False
# this is a copy, no base, does not share memory with arr
d = arr[[1,2], :]
print(d)
print(d.base)
print(np.shares_memory(d, arr))
print(d.flags.owndata)
# [[ 16 32 64 128]
# [ 256 512 1024 2048]]
# None
# False
# True
a
的情况是切片,其中始终返回一个引用。案例c
和d
包含索引,它总是返回一份副本。阅读更多关于它的信息
因此,c
和d
之间的区别是:
对于c
,由于要复制所有行,但只选择列,
内部情况是,原始数组被转置并存储在新的ndarray中;然后删除未选中的列(新nd数组中的行)。然后返回一个转置(从打印c
和c.base
的结果可以看出这一点)
对于d
,由于行是以不连续的方式选择的(该行的所有列)和(好的,取决于),因此直接从原始数组填充(复制,因此没有基)
编辑:
根据信息,当索引不连续的行时(如d
),将复制并堆叠单个行。
扩展这一思想,我假设对于不连续列(如c
),执行三步操作更有意义:
我必须承认,我没有找到这方面的官方文档。对于
a
来说,情况是切片,其中总是返回一个引用。案例c
和d
包含索引,它总是返回一份副本。阅读更多关于它的信息
因此,c
和d
之间的区别是:
对于c
,由于要复制所有行,但只选择列,
内部情况是,原始数组被转置并存储在新的ndarray中;然后删除未选中的列(新nd数组中的行)。然后返回一个转置(从打印c
和c.base
的结果可以看出这一点)
对于d
,由于行是以不连续的方式选择的(该行的所有列)和(好的,取决于),因此直接从原始数组填充(复制,因此没有基)
编辑:
根据信息,当索引不连续的行时(如d
),将复制并堆叠单个行。
扩展这一思想,我假设对于不连续列(如c
),执行三步操作更有意义:
我必须承认,我没有找到这方面的官方文件。你从哪里得到关于
c
案例中转置和放置的信息?相反,我认为它是创建一个(3,2)数组,并复制选定的列。使用strips
numpy可以像索引行一样轻松地索引列。@hpaulj我认为strips
可以帮助numpy确定行结束的界限。这是我的理解。让我觉得,在当前稳定版本的numpy中实现的花式索引
要复杂得多。虽然他们有一个三步的过程,但它与我所提到的完全不同!对于大多数用户来说,c
代码如何制作副本的细节并不重要。这一页,再加上对广播规则的熟悉,应该就足够了。你从哪里得到关于c
案例中转置和放置的信息?相反,我认为它是创建一个(3,2)数组,并复制选定的列。使用strips
numpy可以像索引行一样轻松地索引列。@hpaulj我认为strips
可以帮助numpy确定行结束的界限。这是我的理解。让我觉得,在当前稳定版本的numpy中实现的花式索引
要复杂得多。虽然他们有一个三步的过程,但它与我所提到的完全不同!对于大多数用户来说,c
代码如何制作副本的细节并不重要。这个页面,再加上熟悉广播规则就足够了。b
可以使用a
databuffer,只需使用它自己的偏移量、形状和步幅即可。使用c
和d
不能这样做-列或行已被单独选择(通过列表),因此它们必须有自己的数据缓冲区。如果您不能接受我们的word(或numpy索引文档),您可能需要阅读一些描述数组存储方式的numpy基础知识。我回答了作者最近提出的一些问题,他也试图理解索引。我使用\uuuu数组\u界面\uuuuu
来识别视图
与复制
(我认为这比base
b
可以通过使用a
databuffer本身的偏移量、形状和步幅来提供更多信息。使用c
和d
则无法做到这一点-列或行已被单独选择(通过列表),所以他们必须有自己的数据缓冲。如果你不能接受我们的话(或numpy索引文档),你可能需要阅读一些numpy bas