You need to enable JavaScript to run this app. R大规模用户偏好tibble下全对共现tibble的高效生成方法
优惠活动
大模型
产品
解决方案
定价
更多

R大规模用户偏好tibble下全对共现tibble的高效生成方法

崩溃根因说明
  • 原逐对求交集的方法内存峰值过高:2000种食物的非重复两两对近200万组,每组都需要加载两个食物的完整用户列表、执行集合求交操作,过程中产生的临时对象、列表拷贝会占用数十GB内存,必然触发R的内存溢出崩溃。
  • widyr的报错并非数据量超限:其默认流程会将用户-食物偏好表转为稠密矩阵执行乘法,9.2万行×2000列的稠密矩阵本身就要占用1.5GB以上内存,矩阵转置相乘时Cholmod库因预设缓冲区不足抛出大小限制错误,和实际需要计算的2000×2000共现矩阵规模不匹配。
低内存高效实现方案

核心思路是全程使用稀疏矩阵格式存储数据,从根源上降低内存占用,利用矩阵乘法替代逐对集合求交,计算速度可提升两个数量级。

  1. 构建稀疏用户-食物指示矩阵
    相比逐食物存储用户列表的方式,仅记录非零位置的稀疏矩阵可将内存占用从GB级降到MB级:
    library(Matrix)
    # 因子转整数索引,降低稀疏矩阵创建的额外开销
    food_prefs$person_int <- as.integer(food_prefs$person)
    food_prefs$food_int <- as.integer(food_prefs$food)
    
    # 生成二元稀疏矩阵:行对应用户,列对应食物,值为1代表用户喜欢该食物
    user_food_mat <- sparseMatrix(
      i = food_prefs$person_int,
      j = food_prefs$food_int,
      x = 1,
      dims = c(num_people, num_foods)
    )
    
  2. 计算食物两两共现人数
    利用稀疏矩阵的交叉乘积计算同时喜欢两种食物的用户数,全程走稀疏计算路径,不会触发Cholmod的稠密矩阵大小限制:
    # 得到对称的2000×2000食物共现矩阵
    food_cooccur <- crossprod(user_food_mat)
    
  3. 整理为长格式结果
    仅保留无重复的食物对,和之前计算的期望联合受欢迎程度表合并即可:
    cooccur_long <- summary(food_cooccur) %>% 
      as_tibble() %>% 
      filter(i < j) %>%  # 去掉自对和重复的对称项
      mutate(
        food1 = levels(food_prefs$food)[i],
        food2 = levels(food_prefs$food)[j],
        num_joint = x,
        p_actual_joint = num_joint / num_people
      ) %>% 
      select(food1, food2, num_joint, p_actual_joint)
    
    final_result <- pairwise_popularity_expected %>% 
      left_join(cooccur_long, by = c("food1", "food2"))
    
优化注意事项
  • 全程不要将稀疏矩阵转为稠密格式:哪怕2000×2000的共现矩阵全存为稠密数值也仅占32MB内存,稀疏格式的计算效率远高于稠密矩阵。
  • 若仍需进一步压内存,可分块计算:每次取100个食物列和用户矩阵做交叉乘积,逐块存储结果,内存峰值可控制在100MB以内。
  • 完全避开逐对join用户列表、手动求交集的实现逻辑,这类逻辑在join过程中会反复拷贝列表对象,哪怕最终计算逻辑正确,中间临时对象的内存开销也会远超系统承受范围。

内容的提问来源于stack exchange,提问作者rcorty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 02:06:04