将大型ASCII文件快速读入NumPy数组的最佳方法

3

我有一个大小为1505MB的文本文件,包含浮点数据。该文件大约有73000行和1500列。我想将文件内容读入numpy数组,然后对数组进行分析,但是使用numpy.readtxt读取文件时,我的计算机变得很慢。如何使用Python最快地将此文件读入数组?


2
你说“变慢了”。这里的慢指的是多慢?你使用了多少内存? - user2357112
2
检查 https://dev59.com/J2Up5IYBdhLWcg3wtZTt (使用pandas.read_csv以空格为分隔符) - Lauro Moura
使用 pandas.read_csv 时,我遇到了这个错误 pandas.parser.CParserError: Error tokenizing data. C error: out of memory - Dalek
@Dalek 请参考 https://dev59.com/lWMm5IYBdhLWcg3whPPq 。简而言之,Windows 上的 32 位进程有 2GB 的限制,但我不确定这是否是问题所在。无论如何,还可以通过告诉 pandas CSV 中的类型来节省内存。 - Lauro Moura
73000行1500列的每个浮点数占用8字节,大约为835MB,因此您不应该会耗尽内存。显然,解析部分会导致问题。如果其他方法都失败了,您可以尝试老式的方式,逐行迭代,拆分行,转换结果并将其存储在预先分配的numpy数组中。(补充说明:根据Saulio的答案,它出现在我输入此评论时左右。) - user707650
显示剩余4条评论
2个回答

6

您还可以使用已经优化的pandas读取器:

In [3]: savetxt('data.txt',rand(10000,100))

In [4]: %time u=loadtxt('data.txt')
Wall time: 7.21 s

In [5]: %time u= read_large_txt('data.txt',' ')
Wall time: 3.45 s

In [6]: %time u=pd.read_csv('data.txt',' ',header=None).values
Wall time: 1.41 s

3
以下函数分配所需的内存来读取文本文件。
def read_large_txt(path, delimiter=None, dtype=None):
    with open(path) as f:
        nrows = sum(1 for line in f)
        f.seek(0)
        ncols = len(f.next().split(delimiter))
        out = np.empty((nrows, ncols), dtype=dtype)
        f.seek(0)
        for i, line in enumerate(f):
            out[i] = line.split(delimiter)
    return out

它通过预先知道行数、列数和数据类型来分配内存。您可以轻松添加一些在 np.loadtxt 或 np.genfromtxt 中找到的额外参数,例如 skiprows、usecols 等等。
重要提示:
正如 @Evert 所观察到的那样,out[i] = line.split(delimiter) 似乎是错误的,但 NumPy 将字符串转换为 dtype,无需在此处进行附加的数据类型处理。尽管存在一些限制

1
没有数据类型的强制转换。line.split返回一个字符串数组,所以你需要首先将其转换为一维的numpy数组,并指定数据类型。 - user707650
@Evert 相信我,它是有效的。很可能 NumPy 在将值分配给数组时进行了转换。 - Saullo G. P. Castro
在某种程度上,这让我感到非常害怕:它会崩溃吗?在什么情况下会崩溃?这种行为有没有被记录在某个地方? - user707650
@Evert 这里是一些参考资料 - Saullo G. P. Castro
2
@Dalek:修改那个函数忽略那些行应该不难,对吧? - user707650
显示剩余2条评论

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