【发布时间】:2021-04-12 22:21:30
【问题描述】:
我希望对同一数据有两个不同的视图,其中行的顺序不同,这样通过一个视图所做的更改将反映在另一个视图中。具体如下代码
# 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, 1, 2],
[3, 4, 5],
[6, 7, 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, 2, 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 属性吗?如果是这样,了解如何执行此操作的良好起点是什么?
【问题讨论】:
-
小心第二个链接中的 Zwinck 答案。它狭隘地解决了 OP 问题,不应被视为一般解释。阅读 cmets。
-
基本上没有办法做到这一点,至少在这个问题的狭隘范围内。 Numpy 在连续的内存块上工作;有一些变通方法,但数据的任意排列总是会破坏连续性。真的就这么简单……
-
但是,如果您的基本目标是以置换的方式写入数组,那么您可以很容易地做到这一点——比在问题底部的代码中要容易得多。 (也就是说,除非我误解了您的目标。)但这与您提出的问题完全不同。
-
你想对你的置换数组做什么样的操作?像这样简单的一对一作业还是更复杂的事情?你可以子类化。
-
我的目标是支持不同库使用的不同节点 ID 编号方案,这些库支持有限元网格上的操作。节点坐标的集合没有改变,但分配给它们的全局 ID 不同。我想在不复制网格数据的情况下执行此操作,因为在某些情况下这可能会相当大。
标签: python numpy numpy-slicing numpy-indexing