信不信由你,在分析了我当前的代码之后,numpy数组反转的重复操作占用了大量的运行时间。我现在拥有的是基于视图的通用方法:
reversed_arr = arr[::-1]
有没有其他方法可以更有效地做到这一点,或者这只是我对不切实际的麻木表现的痴迷造成的幻觉?
呃。。。arr[::-1]只是返回一个相反的视图。它尽可能快,而且不依赖于数组中的项目数,因为它只会改变步幅。你要反转的是一个麻木的数组吗?
是的,确实,arr是一个麻木的数组。
六羟甲基三聚氰胺六甲醚。。。好吧,在我的笔记本电脑上,不管阵列的长度是多少,都需要670纳秒。如果这是您的瓶颈,您可能需要切换语言…我很肯定你不会找到一个更快的方法来逆转一个麻木的数组。祝你好运,无论如何!
每击670纳秒和我得到的差不多。运行整个函数的总时间约为2~3秒,其中恢复时间约为1/3,即1秒。因为我要运行这个函数数百万次,所以我认为这是一个瓶颈。如果这确实是我能得到的最好的,大概我只能决定和它一起生活。谢谢!
好吧,你一定要在一个循环中运行它吗?在某些情况下,最好是用数百万个项创建一个麻木的数组,然后对整个数组进行操作。即使您正在执行有限差分法或类似的操作,结果取决于前面的结果,有时也可以执行此操作。(有时强调…)无论如何,如果速度是主要目标,Fortran仍然是王者。以东十一〔二〕是你的朋友!用另一种语言编写算法的性能关键部分(特别是在科学计算中)并从Python中调用它通常是值得的。祝你好运!
我刚刚了解了numpy.flipud(),不知道它与arr[::-1]的性能相比如何。
@贝托。因为它是arr[::-1]的包装器,所以速度较慢:github.com/numpy/numpy/blob/master/numpy/lib/twodim ou base.py。搜索def flipud。这个函数实际上有四行长。
谢谢@madpoisical(顺便说一下,在github上,单击行号,然后复制链接以获取:github.com/numpy/numpy/blob/master/numpy/lib/twodim ou base.py‌&8203;l85)
@贝托。如果你希望你的链接能持续几天以上,这不是个好主意。主分支中的行号经常更改。
创建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)
我不是一个麻木的专家,但这似乎是在麻木中做事情的最快方式。如果这是你已经在做的,我认为你不能改进它。
P.S.关于麻木观点的伟大讨论:
查看一个麻木的数组?
它是否有助于创建一个切片对象,然后在许多数组中重用它?
实际上,我只是测试了它,没有看到与在循环外部创建的slice对象有任何区别。(哦,等等,速度稍微快一点。可重复43.4 ms,而1000000次循环为44.3 ms)
look_at函数的作用是什么?
@它应该代表查看数据的任何任务。该示例的要点是,在基础数据更改之后,视图reversed_arr仍然可用。将新值写入数组不会使视图无效。实际上,您也可以使用该视图向数组中写入新值。reversed_arr[0] = 99将数组中的最后一个元素设置为99,与arr[-1] = 99相同。
如前所述,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,
)
np.fliplr()将数组从左向右翻转。
请注意,对于一维数组,需要稍微欺骗一下:
arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]
号
reversed_arr = np.flipud(arr1d)似乎直接起作用。
因为这似乎还没有被标记为回答…托马斯·阿里森的回答应该是正确的:只用
np.flipud(your_array)
。
如果是一维数组(列数组)。
有母校吗?
fliplr(matrix)
如果要反转行,则返回flipud(matrix),如果要翻转列。无需使一维列数组成为二维行数组(具有一个无层的矩阵),然后翻转它。
我将进一步讨论前面关于np.fliplr()的回答。下面是一些代码,演示如何构造一维数组,将其转换为二维数组,翻转它,然后再转换回一维数组。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
未注释print语句:
[2 1 0]
0.00203907123594
。
打印语句被注释掉:
5.59799927506e-05
所以,在效率方面,我认为这是很好的。对于那些喜欢用一条线来做这件事的人来说,这就是那个形式。
np.fliplr(np.atleast_2d(np.array(range(3))))[0]
。
用这么小的数组计时是非常无用的。如果你想比较一些东西,最好是用一些需要一段时间的东西,比如3000个或者更多的元素。
扩展别人所说的,我将举一个简短的例子。
如果你有一个一维数组…
>>> 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])
。
但是如果你使用的是二维数组…
>>> 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
号
要使其与负数和长列表一起工作,可以执行以下操作:
b = numpy.flipud(numpy.array(a.split(),float))
。
Flipud用于1d阵列