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

3
如何在Python中将一个包含二进制值字符(01)的巨大文本文件(>16G)转换为numpy数组文件,而不会使内存耗尽?假设我们有足够的存储空间,但没有足够的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 ]

1
“二进制值字符串”是什么意思?现有文件的确切格式是什么?根据现有格式,您可能可以使用内存映射数组来处理一些操作。 - user2357112
5
这是一个不错的话题,但提供的信息不足以提供有用的答案。你能发布可以读取较小文件的代码吗?如果不能,请提供有关文件格式等更多信息。 - tom10
这是我用来进行转换的示例代码: - AAA
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - AAA
1
你对导入过程的内存消耗感兴趣吗(通过串行读取和转换数据而不是一次性读取可以减少内存消耗),还是对converted_data的占用空间感兴趣(除非你能利用稀疏结构,否则它将大于1G)? - das-g
显示剩余3条评论
2个回答

2
你可以使用pickle创建多个二进制文件,并编写代码来加载和卸载不同部分的数据。
比如说你有一个16GB的文件,你可以创建16个1GB的pickle文件。
如果你的计算机内存足够,当pickle文件创建完成后,你应该能够将所有数据都加载到内存中。

2
据我所知,您读取文件的方法已经非常节省内存。
我假设使用open获取文件对象不会将整个文件从文件系统读入RAM,而是根据需要访问文件系统中的文件。
然后,您遍历文件对象,逐行生成(在您的情况下是字符串,因为您以文本模式打开了文件),即文件对象充当一个生成器。因此,可以假定这里没有构建所有行的列表,并且逐行读取以连续消耗。
您在列表推导中执行此操作。列表推导是否会在将其右侧(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是否利用了布尔集合可以比数字更有效地存储的事实。但是,如果它确实这样做,您必须让它意识到您的整数实际上是布尔值,以从更节省内存的数据类型中受益:

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 )

正如我的措辞所表明的那样,我的很多结论都是基于猜测的。因此,如果有人知道得更好,请务必纠正我。 - das-g

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