我可以在指定索引处获取numpy数组的视图吗?(来自“花式索引”的视图)

22 投票
4 回答
4550 浏览
提问于 2025-04-16 12:35

我需要一种方法,让“花式索引”(比如 y = x[[0, 5, 21]])返回的是一个视图,而不是一个副本。

我有一个数组,但我想能对这个数组的一个子集进行操作(这个子集是通过一组索引指定的),这样在这个子集上做的修改也能反映到大数组的正确位置上。如果我只想处理前10个元素,我可以直接用普通的切片 y = x[0:10]。这样很好,因为普通切片返回的是一个视图。问题是,如果我不想要0到10,而是想要一组任意的索引,该怎么做呢?

有没有办法做到这一点?

4 个回答

2

这里有一种可能的方法,可以模拟一个视图(就是一些语法上的小花样),通过使用一个“高级视图上下文”来避免在最后写出明确的复制语句。你需要注意的是,确保你的代码在这个上下文中不去修改索引数组。

import contextlib

@contextlib.contextmanager
def fancy_index_view(arr, inds):
    # create copy from fancy inds
    arr_copy = arr[inds]

    # yield 'view' (copy)
    yield arr_copy

    # after context, save modified data
    arr[inds] = arr_copy

现在,这段代码

import numpy as np
foo = np.random.random((22,2))
row_inds = [0,5,21]
barview = foo[row_inds]
barview[::] = 1
foo[row_inds] = barview

可以被替换为

import numpy as np
foo = np.random.random((22,2))
row_inds = [0,5,21]
with fancy_index_view(foo, row_inds) as barview:
    barview[::] = 1
2

你可以直接这样做:

y = x[[0,1,4]]
func(y)
x[[0,1,4]] = y

我觉得用复杂的索引是无法获取视图的。其实你可能也不想这样,因为我觉得复杂索引的速度挺慢的,直接复制数据一次应该会更快。

16

我觉得这个问题没有简单的解决办法。我的理解是,所谓的“花式索引”总是会返回一个副本。对我来说,最好的办法就是先对 y 进行操作,然后再用相同的花式索引来修改 x 的值:

ii = [0, 5, 21]
y = x[ii]
<manipulate y>
x[ii] = y

撰写回答