我发现程序中的瓶颈是从给定值列表中创建numpy数组,最常见的是将4个值放入2x2数组中。有一种明显的,易于阅读的方法:
my_array = numpy.array([[1, 3], [2.4, -1]])
需要15美元 - 非常慢,因为我已经做了数百万次。
然后有一种快得多,难以阅读的方式:
my_array = numpy.empty((2,2))
my_array[0,0] = 1
my_array[0,1] = 3
my_array[1,0] = 2.4
my_array[1,1] = -1
这快10倍,仅为1美元。
是否存在快速且易于阅读的方法?
到目前为止我尝试过:使用asarray
代替array
没有任何区别;将dtype=float
传递给array
也没有任何区别。最后,我明白我可以自己做:
def make_array_from_list(the_list, num_rows, num_cols):
the_array = np.empty((num_rows, num_cols))
for i in range(num_rows):
for j in range(num_cols):
the_array[i,j] = the_list[i][j]
return the_array
这将在4us中创建数组,中速可读性(与上述两种方法相比)。但实际上,我无法相信使用内置方法没有更好的方法。
提前谢谢!!
答案 0 :(得分:9)
这是一个很好的问题。我找不到任何可以接近完全展开的解决方案的速度的内容(编辑 @BiRico能够提出一些接近的东西。请参阅评论并更新 :)。以下是我(和其他人)提出的一系列不同选项以及相关时间:
import numpy as np
def f1():
"np.array + nested lists"
my_array = np.array([[1, 3], [2.4, -1]])
def f2():
"np.array + nested tuples"
my_array = np.array(((1, 3), (2.4, -1)))
def f3():
"Completely unrolled"
my_array = np.empty((2,2),dtype=float)
my_array[0,0] = 1
my_array[0,1] = 3
my_array[1,0] = 2.4
my_array[1,1] = -1
def f4():
"empty + ravel + list"
my_array = np.empty((2,2),dtype=float)
my_array.ravel()[:] = [1,3,2.4,-1]
def f5():
"empty + ravel + tuple"
my_array = np.empty((2,2),dtype=float)
my_array.ravel()[:] = (1,3,2.4,-1)
def f6():
"empty + slice assignment"
my_array = np.empty((2,2),dtype=float)
my_array[0,:] = (1,3)
my_array[1,:] = (2.4,-1)
def f7():
"empty + index assignment"
my_array = np.empty((2,2),dtype=float)
my_array[0] = (1,3)
my_array[1] = (2.4,-1)
def f8():
"np.array + flat list + reshape"
my_array = np.array([1, 3, 2.4, -1]).reshape((2,2))
def f9():
"np.empty + ndarray.flat (Pierre GM)"
my_array = np.empty((2,2), dtype=float)
my_array.flat = (1,3,2.4,-1)
def f10():
"np.fromiter (Bi Roco)"
my_array = np.fromiter((1,3,2.4,-1), dtype=float).reshape((2,2))
import timeit
results = {}
for i in range(1,11):
func_name = 'f%d'%i
my_import = 'from __main__ import %s'%func_name
func_doc = globals()[func_name].__doc__
results[func_name] = (timeit.timeit(func_name+'()',
my_import,
number=100000),
'\t'.join((func_name,func_doc)))
for result in sorted(results.values()):
print '\t'.join(map(str,result))
重要时间:
在Ubuntu Linux上,Core i7:
0.158674955368 f3 Completely unrolled
0.225094795227 f10 np.fromiter (Bi Roco)
0.737828969955 f8 np.array + flat list + reshape
0.782918930054 f5 empty + ravel + tuple
0.786983013153 f9 np.empty + ndarray.flat (Pierre GM)
0.814703941345 f4 empty + ravel + list
1.2375421524 f7 empty + index assignment
1.32230591774 f2 np.array + nested tuples
1.3752617836 f6 empty + slice assignment
1.39459013939 f1 np.array + nested lists
答案 1 :(得分:0)
虽然显然是违反直觉的,但结果并不令人惊讶:NumPy并不是为处理大量非常小的阵列而设计的。相反,它旨在操纵更大的数据数组。
我建议首先创建一个大型数组N*2*2
的大型数组,用数据填充它,然后将其重新整形为(N,2,2)
。
作为旁注,您可能想尝试
def f10():
mine = np.empty((2,2), dtype=float)
mine.flat = (1,3,2.4,-1)
.flat
方法应该比.ravel()[:]=...
方法更有效率(我的个人测试显示它与@mgilson f3
的顺序相同)。