如何将这些ASCII数据读入Python列表或numpy数组?

时间:2013-09-11 20:39:51

标签: python numpy

我有一个ASCII数据文件,其格式在我不熟悉的方面就如何最好地将数据读入Python中的列表或数组。 ASCII数据文件的格式如下:

line 0:          <month> <year>
lines 1 - 217:   12 integer values per line, each value has seven spaces, the first is always a space

例如,文件中的第一条记录如下所示:

    1 1900
 -32768 -32768    790  -1457  -1367    -16   -575    116 -32768 -32768   1898 -32768
 -32768  -1289 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768 -32768
 -32768 -32768    -92 -32768 -32768 -32768    125 -32768 -32768 -32768 -32768 -32768
 -32768 -32768 -32768 -32768 -32768  -1656 -32768   -764 -32768 -32768 -32768 -32768
 <212 more lines like the above for this record, same spacing/separators/etc.>

我将上面的单个记录称为单个记录(单个月的所有数据),文件中大约有1200条记录。在重新开始年份值增加之前,月份从1到12依次增加。我想一次读一个记录,如下所示:

with open(data_file, 'r') as dataFile:
    # while file still has unread records
        # read month and year to use to create a datetime object
        # read the next 216 lines of 12 values into a list (or array) of 2592 values
        # process the record's list (or array) of data

有人可以提出一种有效的“Pythonic”方法来对记录进行上述循环,包括如何最好地将数据读入列表或数组中吗?

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您可以尝试使用生成器函数构建numpy数组,如:

import numpy
def read_input(input_file):
    line_count = 0
    format_line = lambda x : [float(i) for i in x.split()]

    for line in open(input_file):
        if line_count <= 216:
            yield format_line(line)
        else:
            break
        line_count += 1

data = numpy.array([i for i in read_input(input_file)])

这将根据您的问题返回(月,年)和前216个记录。

答案 1 :(得分:1)

itertools.groupby可以在这里使用。

from datetime import date
from itertools import groupby

def keyfunc(line):
    global key
    row = map(int, line.strip().split())
    if len(row) == 2:
        month, year = row
        key = date(year, month, 1)
    return key

def read_file(fname):
    with open(fname, 'r') as f:
        for rec_date, lines in groupby(f, keyfunc):
            data = []
            for line in lines:
                line = map(int, line.strip().split())
                if len(line) == 2:
                    continue
                data.extend(line)
            yield rec_date, data

for rec_date, data in read_file('data.txt'):
    print rec_date, data[:5], '... (', len(data), ")"

keyfunc是聪明的位。它返回每行数据的密钥。 groupby将为具有相同键的每组连续记录生成一个迭代器。 keyfunc是使用global实现的,用于跟踪最新的2值记录(转换为日期)。可以通过更多思考来避免这种全局性。当找到新的2值记录时,它会启动一个以日期为键的新组。数据被聚合到每个键的单个数组中,忽略2值行,因为它们也被返回。最终结果是一个迭代器,它为数据文件中的每个日期返回一个2元组的日期和数据数组。

修改 这是一个简单的选项,不使用itertools.groupby

from datetime import date

def read_file2(fname):
    data = []
    with open(fname, 'r') as f:
        for line in f:
            row = map(int, line.strip().split())
            if len(row) == 2:
                if data:
                    yield key, data
                month, year = row
                key = date(year, month, 1)                
                data = []
            else:
                data.extend(row)
        if data:
            yield key, data


for rec_date, data in read_file2('data.txt'):
    print rec_date, data[:5], '... (', len(data), ")"