如果我们只将矩阵a的一部分赋给另一个变量(view1),这个变量将只显示矩阵的相关组件的视图。但是,如果使用高级索引将矩阵a的一部分分配给另一个变量(view2),则将创建矩阵的相关组件的副本。为什么高级索引(当我们有一个切片参数列表而不是一个元组序列对象)会这样做?我看了文件,但还是不明白。你知道吗
A = np.arange(15)
A = A.reshape((3,5))
print(A, "\n")
view1 = A[:, [3]]
print("'view1' before the matrix A change =", view1)
view2 = A[:, 3]
print("'view2' before the matrix A change =", view2, "\n")
# Change in the 4th column od the matrix A
A[:, 3] = 5
print(A, "\n")
print("'view1' after the matrix A change =", view1)
print("'view2' after the matrix A change =", view2)
首先,我将详细解释您的代码的作用。它创建一个二维3x5矩阵
A
,然后从中创建一个二维3x1列矩阵view1
和一个一维向量view2
。view1
和view2
中的信息与矩阵A
的第四列相同。然后,您的代码会更改矩阵A
,view2
也会收到这些更改,但view1
不会更改。结论是view2
实际上是A
的一个视图,它不是单独的数据,而只是查看矩阵A
的一部分。然而,view1
是A
中信息的副本。创建view1
时,它是单独的数据,刚开始时与A
一致,但可能会出现分歧。你知道吗向量
view2
是A
的视图,因为它的定义A[:, 3]
是第四列A
的基本切片。列矩阵view1
是一个副本,因为它的定义A[:, [3]]
是“高级索引”或“花式索引”。3
周围的括号阻止它成为基本片。定义中的一个细微变化说明了原因:view3 = A[:, [3,0,1]]
创建一个3x3矩阵,该矩阵按顺序包含A
的第四列、第一列和第二列。你知道吗你的问题很好:切片和高级索引的结果看起来很相似,那么为什么第一个是视图,第二个是副本?你知道吗
简单的回答是:为了方便和速度,就像计算机科学中的许多其他决策一样。你知道吗
下面的图形显示了如何在内存中设置numpy数组,与Python的标准列表形成对比。(此图来自Python数据科学手册,第2章,第1节。)
我们看到numpy的数组不是很灵活。数组的维数有一个位置,3x5表示
A
,3x1表示view1
,3表示view2
,3x3表示view3
。之后是跨步,基本上是从一个细胞到下一个细胞在特定维度上的偏移量。对于数组来说就是这样,而不是项值本身。这样可以保持较低的内存使用率,但可以防止Python列表中的列表可以做一些奇特的事情。(我在这里简化了一些细节。)在您的示例中,
A
的数据是第一个维度是行,要从一个单元格转到下一行的相应单元格,numpy必须跳转5个值。例如,第一行第四列的值是
3
。移动到下一行,我们再移动5个位置来查看值8
,而要获得下一行,我们再移动5个位置来获得值13
。第二个维度是列,它的跨距是1:只更改列的3
后面的值是4
。所以矩阵A
的跨步是5
和1
。你知道吗view2
的切片很简单,因此数据与矩阵A
的数据相同。不需要复制数据。那么view2
与A
有什么不同呢?不是像A
的数据指针那样指向值0
,view2
的数据指针指向相同数据中的3
。它的维度块表示只有一个维度有3个值。它只有一个步幅,但它的步幅是5
。换句话说,view2
中的第一个值是3
,为了找到下一个值,numpy跳过5
(步长)位置来找到8
,然后再次找到13
。数组view2
使用与A
相同的数据,但维度和步长不同,因此看起来不同。换句话说,它是A
的视图。你知道吗view3
的高级索引是不同的。在同一行中,值从A
的第四列跳到第一列,再跳到第二列。没有任何步骤可以告诉numpy以这种方式访问这些值。因此,numpy必须从A
复制一些数据,以创建一个新的、简单的数组来处理view3
. 复制是因为无法查看。澄清一下,这是view3
:现在回答你的问题:
view1
怎么样?对于那个特殊的情况,numpy有可能将其视为一种观点。然而,view1
是通过高级索引创建的,我们已经看到,通常不可能为这些创建视图。因此,numpy采用了方便、快速和一致的方法,并声明所有高级索引的场合都会创建副本,即使在视图可能的情况下也是如此。这很方便,因为numpy不需要尝试找出一个视图是否可行。它很快,记住numpy的一个主要优点是它很快,所以在可能的情况下省去创建视图的尝试会加快速度。而且它是一致的,因为所有高级索引的使用都创建副本,而不是一些创建视图和一些创建副本。你知道吗相关问题 更多 >
编程相关推荐