1

我有一些格式为 CSV 的文本文件:

1.3, 0, 1.0
20.0, 3.2, 0
30.5, 5.0, 5.2

这些文件的大小约为 3.5Gb,我无法在有用的时间内将它们中的任何一个读入 Pandas 的内存中。

但我不需要读取所有文件,因为我想做的是从文件中选择一些随机行并读取那里的值,我知道如果文件被格式化,理论上是可以做到的所有字段都具有相同大小的方式 - 例如,二进制文件中的 float16。

现在,我想我可以使用问题答案中指定的 NumPy 方法对其进行转换: How to output list of floats to a binary file in Python

但是,转换完成后如何从中选择随机行?

在普通的文本文件中,我可以这样做:

import random
offset = random.randrange(filesize)
f = open('really_big_file')
f.seek(offset)                  #go to random position
f.readline()                    # discard - bound to be partial line
random_line = f.readline()      # bingo!

但我找不到一种方法可以在由 NumPy 制作的二进制文件中工作。

4

3 回答 3

2

我会struct用来转换为二进制:

import struct
with open('input.txt') as fin, open('output.txt','wb') as fout:
     for line in fin:
         #You could also use `csv` if you're not lazy like me ...
         out_line = struct.pack('3f',*(float(x) for x in line.split(',')))
         fout.write(out_line)

在大多数系统上,这会将所有内容写入标准的 4 字节浮点数。

现在,再次读取数据:

with open('output.txt','rb') as fin:
    line_size = 12 #each line is 12 bytes long (3 floats, 4 bytes each)
    offset = random.randrange(filesize//line_size)  #pick n'th line randomly
    f.seek(offset*line_size) #seek to position of n'th line
    three_floats_bytes = f.read(line_size)
    three_floats = struct.unpack('3f',three_floats_bytes)

如果您担心磁盘空间并希望使用np.float16(2 字节浮点数)压缩数据,您也可以使用上面的基本骨架来做到这一点,只需替换np.fromstringstruct.unpack代替ndarray.tostringstruct.pack当然使用适当的数据类型 ndarray - 并且line_size会下降到 6 ...)。

于 2012-10-09T12:03:55.310 回答
0

因此,使用有用的答案提供的示例,如果有人感兴趣,我找到了一种使用 NumPy 的方法:

# this converts the file from text CSV to bin
with zipfile.ZipFile("input.zip", 'r') as inputZipFile:
    inputCSVFile = inputZipFile.open(inputZipFile.namelist()[0], 'r') # it's 1 file only zip

    with open("output.bin", 'wb') as outFile:
        outCSVFile = csv.writer(outFile, dialect='excel')
        for line in inputCSVFile:
            lineParsed = ast.literal_eval(line)
            lineOut = numpy.array(lineParsed,'float16')
            lineOut.tofile(outFile)
        outFile.close()

    inputCSVFile.close()
    inputZipFile.close()

# this reads random lines from the binary file
with open("output.bin", 'wb') as file:
    file.seek(0)

    lineSize = 20 # float16 has 2 bytes and there are 10 values:
    fileSize = os.path.getsize("output.bin")

    offset = random.randrange(fileSize//lineSize)
    file.seek(offset * lineSize)
    random_line = file.read(lineSize)
    randomArr = numpy.fromstring(random_line, dtype='float16')
于 2012-10-10T16:24:20.587 回答
0

您必须根据存储大小调整偏移量,但是:

import csv
import struct
import random

count = 0
with open('input.csv') as fin, open('input.dat', 'wb') as fout:
    csvin = csv.reader(fin)
    for row in csvin:
        for col in map(float, row):
            fout.write(struct.pack('f', col))
            count += 1


with open('input.dat', 'rb') as fin:
    i = random.randrange(count)
    fin.seek(i * 4)
    print struct.unpack('f', fin.read(4))
于 2012-10-09T12:10:16.393 回答