从数组中选择元素,最小化内存使用

时间:2014-01-12 23:13:52

标签: python numpy bigdata

假设我有一个非常大的np.array有N个元素,我想只选择一些通过S选择的值。通常的方法是:

selected_items = original_array[selection1(original_array) & original_array > 3]

这很好但是使用了很多临时内存。如果我是正确的,我需要S大小为N的布尔值,加上&结果的至少另一个。在内存使用方面是否有更好的解决方案?例如,显式循环不需要:

selected_items = []
tests = (selection1, lambda x: x > 3)
for x in orignal_items:
    if all( (t(x) for t in tests) ):
       selected_items.append(x)

我喜欢numpy,但它的设计真的是内存渴望,所以它似乎不适合处理大数据。另一方面,python中的显式循环不是很有效。

是否有numpy的解决方案?

还有其他基于python的大数据分析框架吗?

4 个答案:

答案 0 :(得分:2)

您可以在使用它来从阵列中选择数据子集之前就地构建选择“掩码”,而不是循环遍历项目。例如:

import numpy as np


x = np.arange(1, 100)

# x less than 75
selection = x < 75

# and greater than 35
selection &= x > 35

# and odd.
selection &= x & 1

print x[selection]

# [37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73]

这不是一个完美的解决方案,但它可能有所帮助。

答案 1 :(得分:1)

Bool存储为一个字节;除非你把你的整个记忆塞满了uint8,否则它不太可能成为一个大问题,相对而言,特别是如果你善于使用就地操作员。但是,如果您的数据几乎不适合内存,那么研究可以有效执行此类查询的磁盘存储可能会很好。 pytables浮出水面;特别是关于大数据的python框架的更一般的问题。

答案 2 :(得分:0)

另一个基于python的框架,主要使用数学是SAGE。内置了许多算法,包括排序和搜索算法。我最近参与了它的RSA建模,但也许你应该尝试一下你的问题。

答案 3 :(得分:0)

布尔选择掩码在RAM中每个空间值占用一个字节。如果您的数据可以放入RAM中,那么布线掩码也有可能适合。

您可以使用就地操作在单个布尔选择掩码中累积选择。通过这种方式,您可以应用任意数量的逻辑运算,并且需要一个选择掩码的固定RAM。

要执行就地布尔操作,您可以使用提供out参数的Numpy Logic Functions。例如:

# (selection1  _AND_  original_array) > 3
mask = selection1(original_array)
mask = np.logical_and(mask, original_array, out=mask)
mask = np.greater(mask, 3, out=mask)

您还可以使用中缀运算符(+=*=,OR和AND)执行就地操作。

如果没有足够的RAM来创建一个布尔掩码,并且所选元素的数量很少,则可以求助于按索引号选择元素。例如,numpy.nonzero()返回每个非零元素的索引。

最后,如果您的数据不适合RAM,那么您可以使用pytables。这允许您在切片中保存和加载数据。 Pytables不仅可以为您提供非常快速的IO操作,还可以使用单个命令对磁盘上的数据集执行非常快速(复杂)的查询(请参阅pytable文档:Expr module)。然而,pytables在开始时可能有点令人生畏。所以如果你有一颗胆小的心(我并不是绝对需要它),我不建议使用它。