首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用布尔或序列对象获取numpy数组的视图(高级索引)

使用布尔或序列对象获取numpy数组的视图(高级索引)
EN

Stack Overflow用户
提问于 2019-02-08 13:42:53
回答 2查看 385关注 0票数 1

如何通过作为索引的numpy数组的布尔值或元组返回numpy数组的视图(而不是副本)?

问题是,这通常会返回一个副本:

当选择对象obj是非元组序列对象、ndarray (数据类型为整型或bool)或至少有一个序列对象或ndarray (数据类型为整型或bool)的元组时,将触发高级索引。高级索引有两种类型:整数索引和布尔索引。 高级索引总是返回数据的副本(与返回视图的基本切片相反)。

我这么做的动机是为了节省记忆。下面是这个问题的一个快速例子:

代码语言:javascript
复制
import numpy as np

big_number = 10
x = np.ones((big_number, big_number, big_number))

#
sub_array = np.s_[(1, 2, 3, 5, 7), :, :]
y = x[sub_array]
print(y.flags['OWNDATA'])

真的

一般来说,索引的元组没有任何结构(1,2,3,5,7),所以我很难理解如何将它按照基本的numpy索引所需的规则步调进行调整。

EN

回答 2

Stack Overflow用户

发布于 2019-02-08 18:03:49

可视化两个数组是否可以共享内存的一种方法是查看它们的“ravel”

代码语言:javascript
复制
In [422]: x = np.arange(24).reshape((4,3,2))
In [423]: x
Out[423]: 
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5]],

       [[ 6,  7],
        [ 8,  9],
        [10, 11]],

       [[12, 13],
        [14, 15],
        [16, 17]],

       [[18, 19],
        [20, 21],
        [22, 23]]])
In [424]: y = x[[1,3,0,2],:,:]  # rearrange the 1st axis
In [425]: y
Out[425]: 
array([[[ 6,  7],
        [ 8,  9],
        [10, 11]],

       [[18, 19],
        [20, 21],
        [22, 23]],

       [[ 0,  1],
        [ 2,  3],
        [ 4,  5]],

       [[12, 13],
        [14, 15],
        [16, 17]]])

In [428]: x.ravel(order='K')
Out[428]: 
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])
In [429]: y.ravel(order='K')
Out[429]: 
array([ 6,  7,  8,  9, 10, 11, 18, 19, 20, 21, 22, 23,  0,  1,  2,  3,  4,
        5, 12, 13, 14, 15, 16, 17])

注意y中的元素是如何以不同的顺序发生的。我们不可能通过x“大步”获得y

除了order参数之外,ravel使用'C',当新数组执行某种轴转置时,这会使我们感到困惑。正如在另一个答案中所指出的,x.T是一个视图,它是通过重新排序轴来实现的,从而改变了进度。

在430: x.T.ravel() # transposed数组中逐行查看Out430: x.T.ravel(0、6、12、18、2、8、14、20、4、10、16、22、1、7、13、19、3、9、15、21、5、11、17、23):x.T.ravel(order='K') # Out431: Out431:Out431( 0,1,2,3,4,5,6,7、8、9、10、11、12、13、14、15、16、17、18、19、20、21、22、23)

__array_interface__是查看数组底层结构的方便工具:

代码语言:javascript
复制
In [432]: x.__array_interface__
Out[432]: 
{'data': (45848336, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (4, 3, 2),
 'version': 3}
In [433]: y.__array_interface__
Out[433]: 
{'data': (45892944, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (4, 3, 2),
 'version': 3}
In [434]: x.T.__array_interface__
Out[434]: 
{'data': (45848336, False),     # same as for x
 'strides': (8, 16, 48),        # reordered strides
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (2, 3, 4),
 'version': 3}
票数 1
EN

Stack Overflow用户

发布于 2019-02-08 14:38:35

NumPy中的视图是基于查看内存中相同的数据,只是有一些不同起点和“跨越式”的混合,必须对每个维度进行遍历。(当索引在每个维度中增加一个时,大步告诉我们需要在数组中移动的字节数。)

如果给定原始数组,您想要的数组可以用这种方式表示,那么将其构造为原始数组的视图应该非常容易。例如,在您的评论中,您提到了调整轴的顺序;这只是对np.transpose的调用,应该给您一个视图。不过,一般说来,高级索引不会为您提供一个正确形式的子数组,这就是为什么NumPy不会从它返回视图。(这还不够“聪明”,无法识别那些可能出现视图的特殊情况--你必须手动进行。)

下面是一些例子:

代码语言:javascript
复制
In [1]: import numpy as np
   ...: x = np.empty((20,30,5))
   ...: x.strides

Out[1]: (1200, 40, 8)

In [2]: y = x.transpose((1,2,0))
   ...: y.strides

Out[2]: (40, 8, 1200)

In [3]: y.flags['OWNDATA']
Out[3]: False

In [4]: z = x[12:1:-2, 1:25:4, :]
   ...: z.strides

Out[4]: (-2400, 160, 8)

In [5]: z.flags['OWNDATA']
Out[5]: False

使用transpose实现transpose的轴来实现y只是改变了前进的步伐。获得z的一个相当复杂的标准索引也改变了步幅(第一步乘以-2,第二步乘以4,因为这是步骤)。

我们可以看到,yz都是视图,因为OWNDATA标志是假的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54593720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档