Python 数组,内存消耗巨大

3

我有一个巨大的文件,第一行是一个字符串,其他行表示整数。列数是可变的,取决于一行的情况。 我有一个全局列表,在其中保存中间结果。arr_of_arr是一个由浮点数列表组成的列表,长度约为5000。该数组的每个元素(再次是数组)的长度为100,000到10,000,000。元素的最大长度可能会有所不同,因此我无法在创建arr_of_arr时提前扩展每个元素。

在我处理完整个文件后,我人为地添加了一些内容,并计算每个全局数组的元素平均值并绘制图表。max_size_arr是数组中最长元素的长度(当我迭代文件行时计算它)。

arr = [x+[0]*(max_size_arr - len(x)) for x in arr_of_arr]

我需要对数组进行逐元素的均值计算。 例如, [[1,2,3],[4,5,6],[0,2,10]] 的计算结果为 [5/3,9/3,19/3](即每个数组中第一个元素的均值,每个数组中第二个元素的均值等等)。
arr = np.mean(np.array(arr),axis=0)

但是,这会导致巨大的内存消耗(根据集群信息可能达到100GB)。在结构上有什么好的解决方案可以减少内存消耗?NumPy数组是否比Python中的普通数组更轻?


你需要改变访问元素的方式,将每个数组的第一个元素存储在自己的数组中,例如[[1,4,0],[2,5,2]]等。听起来像是通过无序访问元素导致内存崩溃。 - scrineym
另一个解决方案是使用yielding,(请参见有关yielding的帖子)。 - Damian
arr_of_arr 应该是一个列表。将其变成对象类型的数组只会使事情更加复杂。 - hpaulj
“normal arrays”是什么意思?Python有列表(lists)。 - hpaulj
@scrineym 我没有乱序访问元素。我的代码使用了 array_of_array 数据结构,导致我只能在集群中使用 100GB 空间,已经超出了限制。 - Alina
@hpaulj 这是一个列表,抱歉。 - Alina
3个回答

1
我认为巨大的内存消耗是因为你想一次性将整个数组放入内存中。
为什么不使用与numpy arrays相结合的切片呢?通过这样做,您可以模拟批量处理数据。您可以给一个函数批处理大小(1000或10000个数组),计算平均值,并将结果写入字典或文件,指示切片及其各自的平均值。

我需要逐列计算平均值,因此首先读取所有行(某些行需要通过添加额外的列来扩展,因为行可以具有不同数量的列),然后再计算平均值。对前1000行和接下来的1000行分别计算平均值对我来说不合适。 - Alina
但是你也可以在上进行切片。 - pazitos10

0
如果行中值的数量差异很大,我会坚持使用列表嵌套列表,只要实际可行。当数据的“行”长度相同时,numpy数组最好。
以下是一个小例子:
In [453]: list_of_lists=[[1,2,3],[4,5,6,7,8,9],[0],[1,2]]

In [454]: list_of_lists
Out[454]: [[1, 2, 3], [4, 5, 6, 7, 8, 9], [0], [1, 2]]

In [455]: [len(x) for x in list_of_lists]
Out[455]: [3, 6, 1, 2]

In [456]: [sum(x) for x in list_of_lists]
Out[456]: [6, 39, 0, 3]

In [458]: [sum(x)/float(len(x)) for x in list_of_lists]
Out[458]: [2.0, 6.5, 0.0, 1.5]

使用数组方法计算平均值时,由于所有填充的0,我得到了不同的数字。这是有意为之吗?

In [460]: max_len=6

In [461]: arr=[x+[0]*(max_len-len(x)) for x in list_of_lists]

In [462]: arr
Out[462]: 
[[1, 2, 3, 0, 0, 0],
 [4, 5, 6, 7, 8, 9],
 [0, 0, 0, 0, 0, 0],
 [1, 2, 0, 0, 0, 0]]

沿列求均值?

In [463]: np.mean(np.array(arr),axis=0)
Out[463]: array([ 1.5 ,  2.25,  2.25,  1.75,  2.  ,  2.25])

沿行求均值

In [476]:     In [463]: np.mean(np.array(arr),axis=1)
Out[476]: array([ 1. ,  6.5,  0. ,  0.5])

最大长度的列表平均值:

In [477]: [sum(x)/float(max_len) for x in list_of_lists]
Out[477]: [1.0, 6.5, 0.0, 0.5]

0

你尝试过使用Numba包吗?它可以通过标准的numpy数组来减少计算时间和内存使用。 http://numba.pydata.org


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接