如果切片没有解决内存错误,如何合并两个大的numpy数组?

时间:2015-07-07 12:49:49

标签: python numpy data-analysis

我有两个numpy数组container1container2 container1.shape = (900,4000)container2.shape = (5000,4000)。使用vstack合并它们会产生MemoryError。在搜索此处发布的旧问题后,我尝试使用slicing合并它们,如下所示:

mergedContainer = numpy.vstack((container1, container2[:1000]))
mergedContainer = numpy.vstack((mergedContainer, container[1000:2500]))
mergedContainer = numpy.vstack((mergedContainer, container[2500:3000]))

但在此之后即使我这样做了:

mergedContainer = numpy.vstack((mergedContainer, container[3000:3100]))

导致MemoryError

我正在使用Python 3.4.3 (32-Bit),希望在不转移到64-Bit的情况下解决。

1 个答案:

答案 0 :(得分:3)

每次拨打np.vstack时,NumPy必须为全新阵列分配空间。 因此,如果我们说1行需要1个单位的内存

np.vstack([container, container2])

需要额外的 900+5000内存单元。而且,在转让之前, Python需要为旧mergedContainer(如果存在)保留空间 作为新mergedContainer的空间。所以建立mergedContainer 迭代地使用切片实际上需要比尝试构建它更多的内存 只需拨打np.vstack

迭代构建它:

| total | mergedContainer | container1 | container2 | temp |                                                                      |
|-------+-----------------+------------+------------+------+----------------------------------------------------------------------|
|  7800 |            1900 |        900 |       5000 |    0 | mergedContainer = np.vstack((container1, container2[:1000]))         |
| 11200 |            3400 |        900 |       5000 | 1900 | mergedContainer = np.vstack((mergedContainer, container[1000:2500])) |
| 13200 |            3900 |        900 |       5000 | 3400 | mergedContainer = np.vstack((mergedContainer, container[2500:3000])) |

从一次调用构建它到np.vstack:

| total | mergedContainer | container1 | container2 | temp |                                                       |
|-------+-----------------+------------+------------+------+-------------------------------------------------------|
| 11800 |            5900 |        900 |       5000 |    0 | mergedContainer = np.vstack((container1, container2)) |
然而,我们可以做得更好。而不是致电np.vstack 反复,分配一次所需的所有空间 一开始并写下container1和。{的内容 container2进入它。换句话说,避免分配两个不同的数组 container1container2,如果您最终知道要合并它们。

container = np.empty((5900, 4000))

请注意basic slices such as container[:900] always return views和视图需要 基本上没有额外的记忆所以你可以定义container1container2喜欢这样:

container1 = container[:900]   
container2 = container[900:]   

然后分配值到位。这会修改container

container1[:] = ...              
container2[:] = ...

因此你的记忆要求将保持在5900左右。

例如,

import numpy as np
np.random.seed(2015)

container = np.empty((5, 4), dtype='int')
container1 = container[:2]   
container2 = container[2:]   
container1[:] = np.random.randint(10, size=(2,4))
container2[:] = np.random.randint(1000, size=(3,4))
print(container)

产量

[[  2   2   9   6]
 [  8   5   7   8]
 [112  70 487 124]
 [859   8 275 936]
 [317 134 393 909]]

虽然只需要一个形状数组(5,4)的空间,以及随机数组的临时空间。

因此,您不必在代码中进行大量更改以节省内存。只需使用

进行设置即可
container = np.empty((5900, 4000))
container1 = container[:900]   
container2 = container[900:]   

然后使用

container1[:] = ...

而不是

container1 = ...

分配值就地。 (或者,当然,您可以直接写入container。)