如何原地反转一个NumPy数组?

3

有没有一种有效的方法来反转NumPy中的原地数组?

注意:我不是在寻找一个反转后的视图。我希望该数组真正被反转。


3
我猜测最好的方法是将倒序的视图复制到原数组中:arr[:]=arr[::-1]。换句话说,数据缓存必须被重写。即使这样做,你可能也会遇到缓存问题。arr[:]=arr[::-1].copy() 可能更安全一些。 - hpaulj
为什么反向观点对你不利? - Julien
1
@Julien:a = numpy.asarray([1, 2, 3]); print(numpy.add(a[::-1], 1, a)) - user541686
1
@Mehrdad:根据NumPy 1.13的文档,numpy.add(a[::-1], 1, a)中的别名问题不再是一个问题。(我相信这是通过创建副本来实现的。) - user2357112
@user2357112:非常感谢您让我知道!我相信我原来的代码更复杂,不完全是那样的,但我现在不确定了...无论如何,这仍然是很好的知识。 - user541686
显示剩余3条评论
2个回答

0

这可能不太优雅,但是如果就地修改是最重要的因素,而运行时间不太重要(因为NumPy切片方法将远远优于迭代方法),您可以始终交换数组左右端点的索引,直到它们收敛:

def reverse(arr):
    ln = arr.shape[0]
    lidx, ridx = 0, ln - 1

    while lidx < ridx:
        rtmp = arr[ridx]
        arr[ridx] = arr[lidx]
        arr[lidx] = rtmp
        lidx += 1
        ridx -= 1

    return arr

这将适用于长度为奇数和偶数的数组。 偶数:

>>> reverse(np.arange(4))
array([3, 2, 1, 0])

奇数:

>>> reverse(np.arange(5))
array([4, 3, 2, 1, 0])

而且为了证明它是原地操作的:

>>> y = np.arange(6)
>>> x = reverse(y)
>>> x is y
True

-1

正如评论中已经指出的那样,这似乎是有效的。

A = np.array([2,1,3])
B = A.copy()
B = B[...,::-1] 

1
这并没有在原地翻转数组,而显然这正是 OP 所要求的。它只是将数据复制到一个新数组中,创建该数组的反转视图,然后用反转视图替换该副本。 - ShadowRanger
谢谢你提醒我。我的帖子应该带有学生驾驶员警告。你能详细说明两者之间的实际区别吗?即在什么情况下你需要其中之一而不需要另一个? - phntm
通常情况下,制作新副本并重新绑定名称是可以的。但有时您会引用别名对象(最常见的是在接收参数时;绑定到参数名称的本地变量通常也绑定到调用者作用域中的名称)。在这些情况下,重新分配不会影响调用者;通常您希望如此(没有意外的副作用),有时则不然。在这种情况下,OP非常清楚地想要原地操作,因此重要的是对原始对象进行原地重写。 - ShadowRanger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接