如何从文本文件映射二维数组

Anu*_*ush 4 python mmap numpy

我有非常大的文件,其中包含正整数的二维数组

  • 每个文件包含一个矩阵

我想在不将文件读入内存的情况下处理它们。幸运的是,我只需要查看输入文件中从左到右的值。我希望能够处理mmap每个文件,这样我就可以像在内存中一样处理它们,但实际上无需将文件读入内存。

较小版本的示例:

[[2, 2, 6, 10, 2, 6, 7, 15, 14, 10, 17, 14, 7, 14, 15, 7, 17], 
 [3, 3, 7, 11, 3, 7, 0, 11, 7, 16, 0, 17, 17, 7, 16, 0, 0], 
 [4, 4, 8, 7, 4, 13, 0, 0, 15, 7, 8, 7, 0, 7, 0, 15, 13], 
 [5, 5, 9, 12, 5, 14, 7, 13, 9, 14, 16, 12, 13, 14, 7, 16, 7]]
Run Code Online (Sandbox Code Playgroud)

是否可以使用mmap这样的文件,以便我可以使用以下方法处理np.int64

for i in range(rownumber):
    for j in range(rowlength):
        process(M[i, j])
Run Code Online (Sandbox Code Playgroud)

需要明确的是,我不想将所有输入文件都放在内存中,因为它不适合。

Mar*_*ell 5

更新答案

根据您的评论和说明,您似乎实际上有一个带有一堆方括号的文本文件,该文件大约有 4 行长,每行有 1,000,000,000 个 ASCII 整数,用逗号分隔。不是一个非常有效的格式!我建议您简单地预处理文件以删除所有方括号、换行符和空格并将逗号转换为换行符,以便每行获得一个您可以轻松处理的值。

使用tr命令音译,就是这样:

# Delete all square brackets, newlines and spaces, change commas into newlines
tr -d '[] \n' < YourFile.txt | tr , '\n' > preprocessed.txt
Run Code Online (Sandbox Code Playgroud)

然后您的文件看起来像这样,您可以轻松地在 Python 中一次处理一个值。

2
2
6
10
2
6
...
...
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Windows,则该tr工具可用于 WindowsGNUWin32中的 Windows 和 Linux 子系统(git bash?)。

你可以更进一步,memmap()在我的答案的第二部分制作一个你喜欢的文件,然后你可以在文件中随机找到任何字节。因此,利用preprocessed.txt上面创建的内容,您可以制作一个二进制版本,如下所示:

import struct

# Make binary memmapable version
with open('preprocessed.txt', 'r') as ifile, open('preprocessed.bin', 'wb') as ofile:
    for line in ifile:
        ofile.write(struct.pack('q',int(line)))
Run Code Online (Sandbox Code Playgroud)

原答案

你可以这样做。第一部分只是设置:

#!/usr/bin/env python3

import numpy as np

# Create 2,4 Numpy array of int64
a = np.arange(8, dtype=np.int64).reshape(2,4)

# Write to file as binary
a.tofile('a.dat')
Run Code Online (Sandbox Code Playgroud)

现在通过在 shell 中十六进制转储来检查文件:

xxd a.dat

00000000: 0000 0000 0000 0000 0100 0000 0000 0000  ................
00000010: 0200 0000 0000 0000 0300 0000 0000 0000  ................
00000020: 0400 0000 0000 0000 0500 0000 0000 0000  ................
00000030: 0600 0000 0000 0000 0700 0000 0000 0000  ................
Run Code Online (Sandbox Code Playgroud)

现在我们都设置好了,让我们来看看memmap()文件:

# Memmap file and access values via 'mm'
mm = np.memmap('a.dat', dtype=np.int64, mode='r', shape=(2,4))

print(mm[1,2])      # prints 6
Run Code Online (Sandbox Code Playgroud)