小编典典

从numpy数组列表创建numpy数组的Python方法

python

我在循环中生成一维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.]])

我的问题如下:

是否有一种更好的方法(性能上)来执行收集顺序数值数据(在我的情况下为numpy数组)的任务,而不是将它们放入列表中,然后从中制成numpy.array(我正在创建新的obj并复制数据)?经过良好测试的模块中是否有可用的“可扩展”矩阵数据结构?

我的2d矩阵的典型大小在100x10到​​5000x10浮动之间

编辑: 在此示例中,我正在使用地图,但是在我的实际应用程序中,我有一个for循环


阅读 218

收藏
2020-12-20

共1个答案

小编典典

假设您知道最终的数组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

这显示numpy_all_the_way使用更少的内存:

% test.py
Initial memory usage: 19788
After python_lists_to_array: 20976
After numpy_all_the_way: 20348

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())
2020-12-20