熊猫读了太多数据

时间:2016-05-24 05:44:00

标签: python pandas optimization memory-management file-descriptor

我试图使用python打开文件格式,对于这个文件,我选择使用pandas(速度和可用性)。

(我将在下面附上完整代码) 用于读取文件的代码段是:

    with open( filename, "rb") as fd:
        hdr={}
        while True:
            pos = fd.tell()
            line = fd.readline().split()

            if line[0] == "SPACE":
                break

            key=line[0]
            for value in line[1:]:
                hdr.setdefault(key, []).append(value)

用它读取文本文件头。 while循环pos之后有一个位置,其中找到了第一个非标题结构(由SPACE文本标记)。该文件将包含许多空间结构(只是一堆数字)。

然后我做了一个小倒带fd.seek(pos)并开始读取数据本身(空间)

        # Building the header
        self.header = {
                [...] 
                'nospaces'    : int(hdr['NOSPACES'][0]),
                'objects'     : hdr['OBJECT']
                }

        # Probably there is a best way to do this
        [...]
        self.nospaces = self.header['nospaces']
        self.objects  = self.header['objects']

        fd.seek(pos)
        self.space=[]

        # Im using range(1) for sake of test
        for i in range(1): #range(self.nospaces): 
            self.space.append(lambda:0)
            line = fd.readline().split()

            # In the first line of SPACE we find a line like this:
            # SPACE 29768 s1_0411_sa
            # Where 28768 is the number of text lines of this space data
            # s1_0411_sa is the space title/name

            self.space[i].lines = int(line[1])
            self.space[i].name = line[2]
            self.space[i].data = pd.read_csv(fd,
                delim_whitespace=True,
                header=None,
                names=self.objects,
                nrows=self.space[i].lines,   # Here I read the exact number of lines
                index_col=(0,1),
                dtype="float32")

但在那之后跑了一个:

fd.tell()
fd.readline()

我没有给我回复下一个SPACE结构数据(因为我希望pandas能够完全读取我要求它的行数)而不是tt让我回到这个位置:1310868和下一行在第二个空间结构之后很长一段随机线的中间。试着理解为什么我得到这个号码:

(1310868-148)/2**16 = 20

我认为,pandas读取缓冲区越来越大,并通过下一个条目。

我不想多次读取文件,一个用于查找空间结构,另一个用于将结构映射到pandas数据帧。

我的问题是,如何让pandas在读取29768空格行后立即停止并返回我的文件描述符。 (s1.space [0] .lines上的值。)

如果没有办法告诉大熊猫,我怎样才能在不读取文件两次或重新映射文​​件的情况下实现这一目标(我想避免内存中的数据重复),因为这些文件可能很大?

遵循完整的可运行代码:

#!/usr/bin/env python

import pandas as pd

class space:
    def read(self, filename):
        with open( filename, "rb") as fd:
            hdr={}
            while True:
                pos = fd.tell()
                line = fd.readline().split()

                if line[0] == "SPACE":
                    break

                key=line[0]
                for value in line[1:]:
                    hdr.setdefault(key, []).append(value)


            # Building the header
            self.header = {
                    'x0'          : int(hdr['XAXIS'][0]),
                    'xinc'       : int(hdr['XAXIS'][1]),
                    'xmax'       : int(hdr['XAXIS'][2]),
                    'y0'          : int(hdr['YAXIS'][0]),
                    'yinc'       : int(hdr['YAXIS'][1]),
                    'ymax'       : int(hdr['YAXIS'][2]),
                    'nospaces'    : int(hdr['NOSPACES'][0]),
                    'objects'     : hdr['OBJECT']
                    }

            # Probably there is a best way to do this
            self.x0          = self.header['x0']
            self.xinc       = self.header['xinc']
            self.xmax       = self.header['xmax']
            self.y0          = self.header['y0']
            self.yinc       = self.header['yinc']
            self.ymax       = self.header['ymax']
            self.nospaces = self.header['nospaces']
            self.objects  = self.header['objects']

            print fd.tell()
            fd.seek(pos)
            self.space=[]
            for i in range(1): #range(self.nospaces):
                self.space.append(lambda:0)
                line = fd.readline().split()
                self.space[i].lines = int(line[1])
                self.space[i].name = line[2]
                self.space[i].data = pd.read_csv(fd,
                    delim_whitespace=True,
                    header=None,
                    names=self.objects,
                    nrows=self.space[i].lines,
                    index_col=(0,1),
                    dtype="float32")

            # This tell() goes far below the self.space[i].lines read.
            print fd.tell()
            print fd.readline()

if __name__ == "__main__":
    s1=space()
    s1.read("data.txt")

数据文件如下所示:

XAXIS 1525 2 1767
YAXIS 1525 2 2011
NOBJECTS 5
NOSPACES 2
OBJECT YAXIS
OBJECT XAXIS
OBJECT XCOORD
OBJECT YCOORD
OBJECT DEPTH
SPACE 29768 s1_0411_sa
1525 1525 125000.01 125000.01 5933.09
1525 1527 125164.05 125000.01 5870.35
[...] then more 29766 lines [...]
SPACE 29768 s2_0411_sa
1525 1525 125000.01 125000.01 19171.9
1525 1527 125164.05 125000.01 18967.5
1525 1529 125328.09 125000.01 18724.8
[...] more 29765 lines [...]

0 个答案:

没有答案