时间感知推荐系统中用户-物品矩阵累积列的并行化构建问询
解决时间感知推荐系统的高效列表生成问题
嘿,我来帮你搞定这个问题!你的需求是给每条用户记录生成当前记录之前按时间戳排序的1分物品列表,原代码虽然能实现功能,但存在两个核心问题:逐行遍历效率极低(大数据集完全跑不动),以及结果的时间顺序无法保证。下面给你一套高效且正确的解决方案:
第一步:确保数据集的时间顺序正确性
首先必须先按user_id和timestamp升序排序,保证每个用户的记录严格按照时间从早到晚排列——这是后续生成有序列表的基础:
# 按用户分组,组内按时间戳升序排序,重置索引避免混乱 df_sorted = df.sort_values(by=['user_id', 'timestamp'], ascending=[True, True]).reset_index(drop=True)
第二步:高效生成目标列表(替代低效的逐行apply)
原代码的最大问题是逐行查询整个数据集,时间复杂度是O(n²),大数据集下完全不可行。我们改用分组累积遍历的方式,时间复杂度降到O(n),效率提升几个数量级:
方案1:原生pandas分组处理(推荐,无额外依赖)
先标记出所有打1分的物品,再针对每个用户维护一个动态列表,遍历过程中逐步生成目标列:
# 第一步:创建临时列,仅保留rating=1的item_id,其余为None df_sorted['temp_item_1'] = df_sorted['item_id'].where(df_sorted['rating'] == 1) # 第二步:定义分组内的累积函数,生成按时间排序的历史1分物品列表 def build_prev_1star_list(series): history_list = [] result = [] for item in series: # 先把当前的历史列表(未包含当前item)存入结果 result.append(history_list.copy()) # 如果当前item是1分物品,加入历史列表 if item is not None: # 如果你需要去重(同一个物品多次打1分只保留第一次),就加个判断: # if item not in history_list: history_list.append(item) return result # 按用户分组应用函数,再展开结果匹配原数据集的行 df_sorted['prev_items_rated_by_usr_with_1'] = ( df_sorted.groupby('user_id')['temp_item_1'] .apply(build_prev_1star_list) .explode(ignore_index=False) .reset_index(level=0, drop=True) ) # 可以删掉临时列 df_sorted.drop(columns=['temp_item_1'], inplace=True)
方案2:超大数据集的并行/分布式处理
如果你的数据集大到原生pandas都扛不住,可以用dask.dataframe来做分布式处理,逻辑和上面一致,只是把pandas的操作换成dask的对应方法;或者用swifter库自动把apply转换成并行执行的版本,只需要把上面的apply换成swifter.apply即可。
关键优势对比
- 时间顺序保证:因为我们先按时间戳排序,且遍历过程是按时间顺序添加物品,所以生成的列表严格按照物品被打1分的时间先后排列。
- 效率爆炸提升:原代码是逐行全表查询,分组处理是每个用户只遍历一次,百万级数据的处理时间会从几小时降到几分钟甚至更短。
- 灵活性高:可以轻松添加去重逻辑(注释里的判断),或者调整列表的生成规则。
内容的提问来源于stack exchange,提问作者Angelo
相关产品推荐
相关产品推荐

