我有一个没有分隔符的.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。有没有更有效的方法将这种类型的数据加载到数组中?
答案 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]))