反转numpy数组的最有效方法

问题:反转numpy数组的最有效方法

信不信由你,在分析当前代码后,执行numpy数组还原的重复操作将占用大量运行时间。我现在拥有的是基于视图的常见方法:

reversed_arr = arr[::-1]

还有其他方法可以更有效地执行此操作,还是我对不切实际的numpy性能的痴迷所致的幻觉?

Believe it or not, after profiling my current code, the repetitive operation of numpy array reversion ate a giant chunk of the running time. What I have right now is the common view-based method:

reversed_arr = arr[::-1]

Is there any other way to do it more efficiently, or is it just an illusion from my obsession with unrealistic numpy performance?


回答 0

创建时,reversed_arr您正在创建原始数组的视图。然后,您可以更改原始数组,并且视图将更新以反映所做的更改。

您是否经常需要重新创建视图?您应该能够执行以下操作:

arr = np.array(some_sequence)
reversed_arr = arr[::-1]

do_something(arr)
look_at(reversed_arr)
do_something_else(arr)
look_at(reversed_arr)

我不是numpy专家,但这似乎是用numpy做事情的最快方法。如果这是您已经在做的,我认为您无法对此进行改进。

PS这里很好的numpy视图讨论:

查看到一个numpy的数组?

When you create reversed_arr you are creating a view into the original array. You can then change the original array, and the view will update to reflect the changes.

Are you re-creating the view more often than you need to? You should be able to do something like this:

arr = np.array(some_sequence)
reversed_arr = arr[::-1]

do_something(arr)
look_at(reversed_arr)
do_something_else(arr)
look_at(reversed_arr)

I’m not a numpy expert, but this seems like it would be the fastest way to do things in numpy. If this is what you are already doing, I don’t think you can improve on it.

P.S. Great discussion of numpy views here:

View onto a numpy array?


回答 1

如上所述,a[::-1]实际上仅创建一个视图,因此它是一个恒定时间的操作(因此,随着数组的增长,它不需要花费更长的时间)。如果您需要数组是连续的(例如,因为您要对其执行许多矢量运算),ascontiguousarray则其速度大约与flipup/ 一样快fliplr


生成绘图的代码:

import numpy
import perfplot


perfplot.show(
    setup=lambda n: numpy.random.randint(0, 1000, n),
    kernels=[
        lambda a: a[::-1],
        lambda a: numpy.ascontiguousarray(a[::-1]),
        lambda a: numpy.fliplr([a])[0],
    ],
    labels=["a[::-1]", "ascontiguousarray(a[::-1])", "fliplr"],
    n_range=[2 ** k for k in range(25)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

As mentioned above, a[::-1] really only creates a view, so it’s a constant-time operation (and as such doesn’t take longer as the array grows). If you need the array to be contiguous (for example because you’re performing many vector operations with it), ascontiguousarray is about as fast as flipud/fliplr:


Code to generate the plot:

import numpy
import perfplot


perfplot.show(
    setup=lambda n: numpy.random.randint(0, 1000, n),
    kernels=[
        lambda a: a[::-1],
        lambda a: numpy.ascontiguousarray(a[::-1]),
        lambda a: numpy.fliplr([a])[0],
    ],
    labels=["a[::-1]", "ascontiguousarray(a[::-1])", "fliplr"],
    n_range=[2 ** k for k in range(25)],
    xlabel="len(a)",
    logx=True,
    logy=True,
)

回答 2

因为这似乎还没有被标记为答案……托马斯·阿里德森的答案应该是正确的:只使用

np.flipud(your_array) 

如果是一维数组(列数组)。

用matrizs做

fliplr(matrix)

如果您想反转行和flipud(matrix)想要反转列。无需将一维列数组设置为二维行数组(具有一个“无”层的矩阵),然后对其进行翻转。

Because this seems to not be marked as answered yet… The Answer of Thomas Arildsen should be the proper one: just use

np.flipud(your_array) 

if it is a 1d array (column array).

With matrizes do

fliplr(matrix)

if you want to reverse rows and flipud(matrix) if you want to flip columns. No need for making your 1d column array a 2dimensional row array (matrix with one None layer) and then flipping it.


回答 3

np.fliplr() 左右翻转数组。

请注意,对于一维数组,您需要进行一些技巧:

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]

np.fliplr() flips the array left to right.

Note that for 1d arrays, you need to trick it a bit:

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]

回答 4

我将在前面有关的答案上进行扩展np.fliplr()。下面的代码演示了如何构建一个1d数组,将其转换为2d数组,翻转它,然后再转换回1d数组。time.clock()将用于保留时间,以秒为单位。

import time
import numpy as np

start = time.clock()
x = np.array(range(3))
#transform to 2d
x = np.atleast_2d(x)
#flip array
x = np.fliplr(x)
#take first (and only) element
x = x[0]
#print x
end = time.clock()
print end-start

带有未打印注释的注释:

[2 1 0]
0.00203907123594

随着打印语句注释掉:

5.59799927506e-05

因此,就效率而言,我认为这很不错。对于那些热爱一线做的人,这里就是这种形式。

np.fliplr(np.atleast_2d(np.array(range(3))))[0]

I will expand on the earlier answer about np.fliplr(). Here is some code that demonstrates constructing a 1d array, transforming it into a 2d array, flipping it, then converting back into a 1d array. time.clock() will be used to keep time, which is presented in terms of seconds.

import time
import numpy as np

start = time.clock()
x = np.array(range(3))
#transform to 2d
x = np.atleast_2d(x)
#flip array
x = np.fliplr(x)
#take first (and only) element
x = x[0]
#print x
end = time.clock()
print end-start

With print statement uncommented:

[2 1 0]
0.00203907123594

With print statement commented out:

5.59799927506e-05

So, in terms of efficiency, I think that’s decent. For those of you that love to do it in one line, here is that form.

np.fliplr(np.atleast_2d(np.array(range(3))))[0]

回答 5

扩展别人的说法,我将举一个简短的例子。

如果您有一维数组…

>>> import numpy as np
>>> x = np.arange(4) # array([0, 1, 2, 3])
>>> x[::-1] # returns a view
Out[1]: 
array([3, 2, 1, 0])

但是如果您正在使用2D阵列…

>>> x = np.arange(10).reshape(2, 5)
>>> x
Out[2]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> x[::-1] # returns a view:
Out[3]: array([[5, 6, 7, 8, 9],
               [0, 1, 2, 3, 4]])

这实际上并不会反转矩阵。

应该使用np.flip实际反转元素

>>> np.flip(x)
Out[4]: array([[9, 8, 7, 6, 5],
               [4, 3, 2, 1, 0]])

如果要一张一张地打印矩阵的元素,请同时使用平面和翻转

>>> for el in np.flip(x).flat:
>>>     print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0

Expanding on what others have said I will give a short example.

If you have a 1D array …

>>> import numpy as np
>>> x = np.arange(4) # array([0, 1, 2, 3])
>>> x[::-1] # returns a view
Out[1]: 
array([3, 2, 1, 0])

But if you are working with a 2D array …

>>> x = np.arange(10).reshape(2, 5)
>>> x
Out[2]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> x[::-1] # returns a view:
Out[3]: array([[5, 6, 7, 8, 9],
               [0, 1, 2, 3, 4]])

This does not actually reverse the Matrix.

Should use np.flip to actually reverse the elements

>>> np.flip(x)
Out[4]: array([[9, 8, 7, 6, 5],
               [4, 3, 2, 1, 0]])

If you want to print the elements of a matrix one-by-one use flat along with flip

>>> for el in np.flip(x).flat:
>>>     print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0

回答 6

为了使它可以使用负数和长列表,您可以执行以下操作:

b = numpy.flipud(numpy.array(a.split(),float))

凡翻页是一维arra

In order to have it working with negative numbers and a long list you can do the following:

b = numpy.flipud(numpy.array(a.split(),float))

Where flipud is for 1d arra