提问者:小点点

Python列表追加需要很长时间?


我有一个函数,为每个用户(4000个用户)找到一个给定列表(一个列表)和其他列表(60,000个列表)之间的常见,不常见项目及其费率。 运行以下循环需要太长的时间和高内存使用率,部分列表构造和崩溃。 我认为由于返回的列表很长,而且元素(元组)很重,所以我将它分成了两个函数,如下所示,但是在元组中添加列表项时似乎有问题,[(user,[items],rate),(user,[items],rate),...]。 我想从返回的值创建一个数据帧,

我应该对一个算法做些什么来绕过这件事并减少内存使用?

我正在使用python 3.7,windows 10,64位,RAM 8g。

常用项功能:

def common_items(user,list1, list2):

    com_items = list(set(list1).intersection(set(list2)))
    com_items_rate = len(com_items)/len(set(list1).union(set(list2))) 
    
       
    return user, com_items, com_items_rate

不常用项功能:

def uncommon_items(user,list1, list2):

    com_items = list(set(list1).intersection(set(list2)))
    com_items_rate = len(com_items)/len(set(list1).union(set(list2))) 
    
    
    uncom_items = list(set(list2) - set(com_items)) # uncommon items that blonge to list2
    uncom_items_rate = len(uncom_items)/len(set(list1).union(set(list2)))
    
    return user, com_items_rate, uncom_items, uncom_items_rate # common_items_rate is also needed 

构建列表:

common_item_rate_tuple_list = [] 

for usr in users: # users.shape = 4,000
    list1 = get_user_list(usr) # a function to get list1, it takes 0:00:00.015632 or less for a user
#     print(usr, len(list1))            

    for list2 in df["list2"]: # df.shape = 60,000

        common_item_rate_tuple = common_items(usr,list1, list2) 
        common_item_rate_tuple_list.append(common_item_rate_tuple)
        
print(len(common_item_rate_tuple_list)) # 4,000 * 60,000 = 240,000,000‬ items
# sample of common_item_rate_tuple_list:
#[(1,[2,5,8], 0.676), (1,[7,4], 0.788), ....(4000,[1,5,7,9],0.318), (4000,[8,9,6],0.521)

我看了(记忆错误和列表限制?) 和(在Python中追加到列表时的内存错误),它们处理的是构造的列表。 我无法处理建议的答案(Python列表内存错误)。


共1个答案

匿名用户

对于这么大的数据,您应该考虑几件事情来实现速度和内存管理。

  • 您现在或应该只使用,因为顺序在列表中没有意义,而且您正在进行许多集的相交。 那么,是否可以更改get_user_list()函数以返回集合而不是列表呢? 这将防止所有不必要的转换你正在做。 与清单2相同,只需立即创建一个集合
  • 在查找“不常见项”时,只需在集合上使用对称差分运算符即可。 快得多,少得多的列表->; 设置转换
  • 在循环结束时,您真的要创建一个包含240M个子列表的列表吗? 那很可能是你的记忆力爆炸。 我建议用键作为用户名的字典。 并且您只需要在其中创建一个条目(如果有公共项)。 如果存在“稀疏”匹配,您将得到一个小得多的数据容器