You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

时间感知推荐系统中用户-物品矩阵累积列的并行化构建问询

解决时间感知推荐系统的高效列表生成问题

嘿,我来帮你搞定这个问题!你的需求是给每条用户记录生成当前记录之前按时间戳排序的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:55:12