如何解决创建一个 numpy 数组的置换浅拷贝
我希望有相同数据的两个不同视图,行的顺序不同,这样通过一个视图所做的更改将反映在另一个视图中。具体如下代码
# Create original array
A = numpy.array([[0,1,2],[3,4,5],[6,7,8]])
B = A.view()[[0,2,1],:] # Permute the rows
print("(before) B =\n",B)
# Change a value in A
A[1,2] = 143
print("(after) A =\n",A)
print("(after) B =\n",B)
具有以下输出:
(before) B =
[[0 1 2]
[6 7 8]
[3 4 5]]
(after) A =
[[ 0 1 2]
[ 3 4 143]
[ 6 7 8]]
(after) B =
[[0 1 2]
[6 7 8]
[3 4 5]]
但我想要最后一点
(after) B =
[[0 1 2]
[6 7 8]
[3 4 143]]
对 this question 的回答指出,在 特定索引 处获得视图是不可能的,尽管该问题的 OP 是询问数组的一个子集,而我想要一个视图整个数组。 (这里的主要区别似乎是切片与智能索引)
一个 different post 询问关于按 行然后列 与 列然后行 进行切片的问题有一个公认的答案,指出 “所有重要的是无论您是按行切片还是按列切片...”。所以我尝试处理数组的扁平视图..
A = numpy.array([[0,8]])
B = A.view()
B.shape = (A.size,)
A[1,2] = 198
print("(After first) A =\n",A)
print("(After first) B =\n",B)
# Identity index map
all_idx = numpy.arange(A.size).reshape(A.shape)
# Swapped and flattened index map
new_row_idx = all_idx[[0,1]].flatten()
C = B[new_row_idx]
print("(Before second) C =\n",C)
# Manipulate through 'B'
B[7] = 666
print("(After second) B =\n",B)
print("(After second) C =\n",C)
给出以下输出:
(After first) A =
[[ 0 1 2]
[ 3 4 198]
[ 6 7 8]]
(After first) B =
[ 0 1 2 3 4 198 6 7 8]
(Before second) C =
[ 0 1 2 6 7 8 3 4 198]
(After second) B =
[ 0 1 2 3 4 198 6 666 8]
(After second) C =
[ 0 1 2 6 7 8 3 4 198]
如您所见,C
的第 4 个条目未更改。 first post I mentioned 的建议解决方案是创建一个副本,进行更改,然后更新原始数组。我可以编写函数来包装它,但这并不能消除我制作副本的次数。它所做的只是对用户隐藏它。
我在这里错过了什么?我应该使用这些数组的 data
属性吗?如果是这样,了解如何执行此操作的良好起点是什么?
解决方法
一个数组有一个 shape
、strides
、dtype
和 1d data_buffer。 view
将拥有自己的 shape
、strides
、dtype
和指向 base 的 data_buffer 中某个位置的指针。仅使用这些属性即可实现使用 slice
的索引。
但是不能通过这种方式实现使用诸如 [0,2,1] 之类的列表进行索引。所以 numpy
用它自己的 data_buffer 创建了一个新数组,一个 copy
。 [0,1] 索引列表/数组不与副本一起存储。
In [43]: A = np.arange(9).reshape(3,3)
In [44]: B = A[[0,1],:]
In [45]: A
Out[45]:
array([[0,1,2],[3,4,5],[6,7,8]])
In [46]: B
Out[46]:
array([[0,8],5]])
ravel
显示数据库中元素的顺序:
In [47]: A.ravel()
Out[47]: array([0,3,5,6,8])
B
中元素的顺序不同。
In [48]: B.ravel()
Out[48]: array([0,8,5])
相反,考虑使用切片对行进行重新排序:
In [49]: C = A[::-1,:]
In [50]: C
Out[50]:
array([[6,[0,2]])
In [52]: A.strides
Out[52]: (24,8)
这是通过简单地更改 strides
来实现的:
In [53]: C.strides
Out[53]: (-24,8)
转置也是一种视图,但步幅发生了变化:
In [54]: D = A.T
In [55]: D.strides
Out[55]: (8,24)
我本来打算展示 C.ravel()
,但意识到 reshape 会生成一个副本(即使 C
是一个视图)。
基本点是,numpy
描述为 advanced indexing
的任何内容都会复制。对副本的更改不会出现在原始数组中。 https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。