【问题标题】:Extracting a random line in a file without loading the file into RAM in python在python中提取文件中的随机行而不将文件加载到RAM中
【发布时间】:2014-03-02 17:00:34
【问题描述】:

我有用于机器学习目的的大型 svmlight 文件。我正在尝试查看这些文件的总采样是否会产生足够好的结果。

我想提取文件的随机行以将它们提供给我的模型,但我想在 RAM 中加载不太可能的信息。

我在这里 (Read a number of random lines from a file in Python) 看到我可以使用 linecache,但所有解决方案最终都会将所有内容加载到内存中。

有人可以给我一些提示吗?谢谢你。

编辑:忘了说我事先知道文件中的行数。

【问题讨论】:

    标签: python file svmlight


    【解决方案1】:

    您可以使用heapq 根据随机数选择n条记录,例如:

    import heapq
    import random
    
    SIZE = 10
    with open('yourfile') as fin:
        sample = heapq.nlargest(SIZE, fin, key=lambda L: random.random())
    

    这是非常有效的,因为 heapq 保持固定大小,它不需要预先扫描数据并且元素被替换为其他元素被选择 - 所以最多你会得到SIZE内存中的元素。

    【讨论】:

    • 我忘了说我知道我的文件中的行数,我不能利用它吗?
    • @AdrienNK 唯一的好处是,如果您的行是固定长度的,这样您就可以在生成 0 到 行之间的 n 个整数后直接查找每条记录文件...否则,它没有任何优势...
    • 好的,谢谢您的回答。我仍然不确定究竟什么是记录,但我会调查一下!
    • 我认为这样做的目的是避免阅读整个文件。如果文件足够大以至于将它们加载到内存中是一个问题,那么 I/O 时间会不会占主导地位?
    • @holdenweb 我不知道...我正在研究 但我想在 RAM 中加载不太可能的信息。 这样做(并且对于所有我们知道 - 他们正在耗尽 SSD - 所以 i/o 时间不一定是这样的负担)......我已经提到如果行的长度是固定的,那么寻找是实用的,我刚刚注意到你已经介绍了寻找并找到他们不在的地方的一个例子。我认为如果性能成为问题,那么 OP 就可以根据他们的具体情况尝试替代解决方案。
    【解决方案2】:

    一种选择是对文件进行随机搜索,然后在读取一行之前向后查找换行符(或文件的开头)。这是一个程序,它打印在当前目录中找到的每个 Python 程序的随机行。

    import random
    import os
    import glob
    
    for name in glob.glob("*.py"):
        mode, ino, den, nlink, uid, gid, size, atime,  mtime, ctime = os.stat(name)
        inf = open(name, "r")
        location = random.randint(0, size)
        inf.seek(location)
        while location > 0:
            char = inf.read(1)
            if char == "\n":
                break
            location -= 1
            inf.seek(location)
        line = inf.readline()
        print name, ":", line[:-1]
    

    只要线条不是很大,这应该不会过于繁重。

    【讨论】:

    • 这个解决方案在 ASCII 世界中很好(在我看来,无论如何),但是多字节可变长度编码的变幻莫测意味着在使用 Unicode 时它不能被认为是可靠的。此代码也不能移植到 Python 3。
    【解决方案3】:

    您可以扫描文件一次,计算行数。一旦知道这一点,您就可以生成随机行号,重新读取文件并在看到该行时发出该行。

    其实既然你对多行感兴趣,你应该看看Efficiently selecting a set of random elements from a linked list

    【讨论】:

    • 大文件重读会不会效率极低? (我说的是 >10Gb 文件)
    • 是的,在这种情况下,您可能应该使用水库采样技术
    猜你喜欢
    • 1970-01-01
    • 2015-08-07
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 2020-01-16
    相关资源
    最近更新 更多