Dra*_*ric 40 python arrays performance numpy scipy
我在循环中生成一维numpy数组的列表,然后将此列表转换为2d numpy数组.如果我提前知道项目的数量,我会预先分配一个2d numpy数组,但我没有,因此我将所有内容都放在列表中.
模拟如下:
>>> list_of_arrays = map(lambda x: x*ones(2), range(5))
>>> list_of_arrays
[array([ 0., 0.]), array([ 1., 1.]), array([ 2., 2.]), array([ 3., 3.]), array([ 4., 4.])]
>>> arr = array(list_of_arrays)
>>> arr
array([[ 0., 0.],
[ 1., 1.],
[ 2., 2.],
[ 3., 3.],
[ 4., 4.]])
Run Code Online (Sandbox Code Playgroud)
我的问题如下:
是否有更好的方法(性能方面)来完成收集顺序数字数据(在我的情况下是numpy数组)的任务,而不是将它们放在一个列表中然后从中创建一个numpy.array(我正在创建一个新的obj并复制数据)?在经过良好测试的模块中是否有"可扩展"矩阵数据结构?
我的2d矩阵的典型大小将介于100x10和5000x10浮点之间
编辑:在这个例子中我使用map,但在我的实际应用程序中,我有一个for循环
Gil*_*tes 20
方便的方式,使用numpy.concatenate.我相信它也比@ unutbu的答案更快:
In [32]: import numpy as np
In [33]: list_of_arrays = list(map(lambda x: x * np.ones(2), range(5)))
In [34]: list_of_arrays
Out[34]:
[array([ 0., 0.]),
array([ 1., 1.]),
array([ 2., 2.]),
array([ 3., 3.]),
array([ 4., 4.])]
In [37]: shape = list(list_of_arrays[0].shape)
In [38]: shape
Out[38]: [2]
In [39]: shape[:0] = [len(list_of_arrays)]
In [40]: shape
Out[40]: [5, 2]
In [41]: arr = np.concatenate(list_of_arrays).reshape(shape)
In [42]: arr
Out[42]:
array([[ 0., 0.],
[ 1., 1.],
[ 2., 2.],
[ 3., 3.],
[ 4., 4.]])
Run Code Online (Sandbox Code Playgroud)
unu*_*tbu 19
假设您知道最终数组arr永远不会大于5000x10.然后你可以预先分配一个最大大小的数组,在循环中用数据填充它,然后arr.resize在退出循环后用它将它减少到发现的大小.
下面的测试表明,无论数组的最终大小是什么,这样做都会比构建中间python列表稍快一些.
此外,arr.resize取消分配未使用的内存,因此最终(尽管可能不是中间)内存占用量小于使用的内存python_lists_to_array.
这个节目numpy_all_the_way更快:
% python -mtimeit -s"import test" "test.numpy_all_the_way(100)"
100 loops, best of 3: 1.78 msec per loop
% python -mtimeit -s"import test" "test.numpy_all_the_way(1000)"
100 loops, best of 3: 18.1 msec per loop
% python -mtimeit -s"import test" "test.numpy_all_the_way(5000)"
10 loops, best of 3: 90.4 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(100)"
1000 loops, best of 3: 1.97 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(1000)"
10 loops, best of 3: 20.3 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(5000)"
10 loops, best of 3: 101 msec per loop
Run Code Online (Sandbox Code Playgroud)
这显示numpy_all_the_way使用更少的内存:
% test.py
Initial memory usage: 19788
After python_lists_to_array: 20976
After numpy_all_the_way: 20348
Run Code Online (Sandbox Code Playgroud)
test.py:
import numpy as np
import os
def memory_usage():
pid = os.getpid()
return next(line for line in open('/proc/%s/status' % pid).read().splitlines()
if line.startswith('VmSize')).split()[-2]
N, M = 5000, 10
def python_lists_to_array(k):
list_of_arrays = list(map(lambda x: x * np.ones(M), range(k)))
arr = np.array(list_of_arrays)
return arr
def numpy_all_the_way(k):
arr = np.empty((N, M))
for x in range(k):
arr[x] = x * np.ones(M)
arr.resize((k, M))
return arr
if __name__ == '__main__':
print('Initial memory usage: %s' % memory_usage())
arr = python_lists_to_array(5000)
print('After python_lists_to_array: %s' % memory_usage())
arr = numpy_all_the_way(5000)
print('After numpy_all_the_way: %s' % memory_usage())
Run Code Online (Sandbox Code Playgroud)
fnj*_*njn 13
甚至比@Gill Bates的回答简单,这里是一行代码:
np.stack(list_of_arrays, axis=0)
Run Code Online (Sandbox Code Playgroud)