我有一个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”方法来对记录进行上述循环,包括如何最好地将数据读入列表或数组中吗?
提前感谢您的帮助!
答案 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), ")"