我有一个巨大的python列表(A)列表。列表A的长度约为90,000。每个内部列表包含大约700个(datetime.date,string)
元组。现在,我正在分析这些数据。我正在做的是我在内部列表中使用一个大小为x的窗口 - x = len(inner list) * (some fraction <= 1)
并且我保存每个有序对(a,b),其中a出现在该窗口中的b之前(实际上内部列表被排序为wrt时间)。我正在将这个窗口移动到最后一个元素,从最后一个元素一端添加一个元素,然后从另一个元素移除O(window-size)
时间,因为我只考虑新的元组。我的代码:
for i in xrange(window_size):
j = i+1;
while j<window_size:
check_and_update(cur, my_list[i][1], my_list[j][1],log);
j=j+1
i=1;
while i<=len(my_list)-window_size:
j=i;
k=i+window_size-1;
while j<k:
check_and_update(cur, my_list[j][1], my_list[k][1],log);
j+=1
i += 1
这里cur
实际上是一个sqlite3数据库游标,my_list
是一个包含元组的列表,我为A中的所有列表迭代此代码,log
是一个打开的日志文件。在方法check_and_update()
中,我正在查找我的数据库,以查找存在的元组,或者我插入它,以及它到目前为止的总发生次数。代码:
def check_and_update(cur,start,end,log):
t = str(start)+":"+ str(end)
cur.execute("INSERT OR REPLACE INTO Extra (tuple,count)\
VALUES ( ? , coalesce((SELECT count +1 from Extra WHERE tuple = ?),1))",[t,t])
正如预期的那样,这个元组的数量是巨大的,我之前已经尝试过字典,它可以很快地占用内存。所以,我使用SQLite3,但现在它太慢了。我试过索引,但没有帮助。可能我的程序花了很多时间来查询和更新数据库。您对此问题有任何优化想法吗?可能会改变算法或一些不同的方法/工具。谢谢!
编辑:我的目标是找到窗口中出现的字符串元组的总数,这些元组按其出现的不同内部列表的数量分组。我使用此查询提取此信息:< / p>
for i in range(1,size+1):
cur.execute('select * from Extra where count = ?',str(i))
#other stuff
例如(我忽略日期条目并将它们写为'dt'):
My_list = [
[ ( dt,'user1') , (dt, 'user2'), (dt, 'user3') ]
[ ( dt,'user3') , (dt, 'user4')]
[ ( dt,'user2') , (dt, 'user3'), (dt,'user1') ]
]
如果我将fraction = 1,则结果:
only 1 occurrence in window: 5 (user 1-2,1-3,3-4,2-1,3-1)
only 2 occurrence in window: 2 (user 2-3)
答案 0 :(得分:2)
让我直截了当。
您有多达220亿个潜在元组(90000个列表,700个中的任何一个,以下任何条目,平均350个),根据窗口大小的不同,可能会更少。你想找到,但它们出现的内部列表的数量,有多少元组。
此大小的数据必须存在于磁盘上。由于大小而存在于磁盘上的数据规则是“从不随机访问,而是生成然后排序。”
所以我建议你把每个元组写成一个日志文件,每行一个元组。对该文件进行排序现在任何给定元组的所有实例都在一个地方。然后运行该文件,并为每个元组发出它出现的次数(即它所在的内部列表的数量)。排序第二个文件。现在运行该文件,您可以提取有多少元组出现1x,2x,3x等。
如果你有多台机器,很容易将其转换为MapReduce。 (这在道德上是相同的方法,但你可以并行化许多东西。)
答案 1 :(得分:1)
Apache Hadoop是适用于此类问题的MapReduce实现之一: