读取.dat没有分隔符到python中的数组

时间:2014-04-15 00:16:54

标签: python arrays

我有一个没有分隔符的.dat文件,我试图读入数组。假设每个新行代表一个人,并且每行中的变量是根据固定数量的字符定义的,例如,第一个变量“year”是前四个字符,第二个变量“age”是接下来的两个字符(no行内的分隔符)例如:

201219\n
201220\n
201256\n

这就是我现在正在做的事情:

data_file = 'filename.dat'
file = open(data_file, 'r')

year = []
age = []

for line in file:   
    year.append(line[0:4])
    age.append(line[4:])

这适用于少量的行和变量,但是当我尝试加载完整的数据文件(500Mb,1000万行和20个变量)时,我得到一个MemoryError。有没有更有效的方法将这种类型的数据加载到数组中?

3 个答案:

答案 0 :(得分:1)

首先,从软件工程的角度来看,你可能更适合使用类实例列表而不是一堆并行列表。如果您尝试这样做,您可能应该调查__slots__以减少内存开销。

你也可以尝试pypy - 它对同类列表有一些内存优化。

如果你想要一个磁盘上的解决方案,我可能会使用gdbm或bsddb而不是sqlite。 gdbm和bsddb看起来像dict,除了用字符串索引它们(键),值也是字符串。因此,您的类(我上面提到的那个)将有__str__和/或__repr__方法,这些方法将转换为字符串(可以使用pickle)存储在表中。然后你的构造函数将以某种方式处理逆转过程。

如果你得到如此大的数据,以至于gdbm或bsddb太慢了,你可以尝试只写一个平面文件 - 这显然不是很好跳,但它消除了很多寻求( )有时可能非常有利。

HTH

答案 1 :(得分:0)

这里的问题似乎并不是因为你把它读入内存时遇到了问题。当你在谈论内存中的2亿个时,你会遇到一些问题。

尝试将其存储为字符串列表(即CPU的交易内存),或者根本不存储它。

尝试的另一个选择是将其转储到sqlite数据库中。如果你使用内存中的数据库,你可能会遇到同样的问题,但可能没有。

如果您选择字符串样式,请执行以下操作:

def get_age(person):
    return int(person[4:])


people = file.readlines()  # Wait a while....

for person in people:
    print(get_age(person)*2)  # Or something else

以下是在特定年份获得特定年龄的平均收入的示例:

def get_mean_income_by_age_and_year(people, target_age, target_year):
    count = 0
    total = 0.0
    for person in people:
        income, age, year = get_income(person), get_age(person), get_year(person)
        if age == target_age and year == target_year:
            total += income
            count += 1
    if count:
        return total/count
    else:
        return 0.0

但是,实际上,这基本上可以将它存储在sqlite数据库中。如果你想做的只有几件非常具体的事情,那么走这条路可能是合理的。但听起来你可能想用这些信息做几件事 - 如果是这样,sqlite数据库可能就是你想要的。

答案 2 :(得分:0)

数组中有许多统一数字数据的更有效的数据结构。根据您拥有的内存量,使用数组可能会有效。

import array

year = array.array('i')    # int
age = array.array('i')     # int
income = array.array('f')  # float

with open('data.txt', 'r') as f:
  for line in f:
    year.append(int(line[0:4]))
    age.append(int(line[4:6]))
    income.append(float(line[6:12]))