将二进制值的文本转换为numpy文件

时间:2015-06-17 22:07:56

标签: python memory numpy text

如何将包含二进制值字符(01)的大文本文件(> 16G)转换为numpy数组文件而不会在python中炸毁内存?假设我们在机器上有足够的存储空间但没有足够的RAM用于转换。

示例数据:

0,0,0,0,0,1,0,0,0 
1,0,0,1,0,0,0,0,0
...

示例代码:

converted_data = [ map(int,line.split(',')) for line in f ]

2 个答案:

答案 0 :(得分:2)

您创建了许多带有pickle的bin文件,并且您有一些代码可以加载和卸载数据的不同部分。

假设你有一个16GB的文件,你可以创建16个1GB的pickle文件。

如果你说你有足够的内存,那么在完成pickle文件之后,你应该能够将它全部加载到内存中。

答案 1 :(得分:2)

据我所知,您阅读文件的方法已经非常有效。

我假设获取open的文件对象将整个文件从文件系统读入RAM,而是根据需要访问文件系统上的文件。 / p>

然后迭代文件对象yields the file's lines(在您的情况下为字符串,因为您已经在文本模式下打开文件),即文件对象充当{{ 3}}。因此可以假设这里没有构建所有行的列表,并且逐行读取这些行以便连续消耗。

您可以在列表收缩中执行此操作。列表收缩是否收集了右侧产生的所有值(in关键字后面的部分),然后将其传递到左侧(for关键字之前的部分)进行处理?一个小实验可以告诉我们:

print('defining generator function')

def firstn(n):
        num = 0
        while num < n:
                print('yielding ' + str(num))
                yield num
                num += 1

print('--')

[print('consuming ' + str(i)) for i in firstn(5)]

以上的输出是

defining generator function
--
yielding 0
consuming 0
yielding 1
consuming 1
yielding 2
consuming 2
yielding 3
consuming 3
yielding 4
consuming 4

所以答案是否定的,在从右手边产生任何其他值之前,左手边会立即消耗每个屈服值。文件中只有一行必须一次保存在内存中。

因此,如果您文件中的各行不长,您的阅读方式似乎就像内存效率一样

当然,你的列表收缩仍然需要收集左手边处理的结果。毕竟,结果列表是您想要摆脱这一切的原因。因此,如果内存不足,结果列表可能会变得太大。

我不知道NumPy是否使用了这样一个事实,即布尔的集合可以比数字更有效地存储。但 if 确实如此,你必须让它意识到你的整数实际上是布尔值,以便从更高内存效率的数据类型中受益:

import numpy as np
f = open ( "data.txt" , 'r')
converted_data = [ np.fromstring(line, dtype=bool, sep=',') for line in f ]

如果您不是一次需要所有converted_data,而是必须能够迭代它,请考虑将其设为生成器,而不是列表。您不需要使用yield关键字来实现这一目标。只需用圆括号替换列表理解的方括号,就可以得到生成器表达式:

converted_data_generator = ( np.fromstring(line, dtype=bool, sep=',') for line in f )