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

R语言DataFrame聚合填充效率优化:替代低效三重循环方案

哇,三重循环处理要4天确实太折磨了!咱们用aggregate配合数据重塑的方法,能把效率提升几个数量级,直接把处理时间压缩到分钟甚至秒级。下面是具体的实现步骤:

第一步:先聚合用户-视频的总观看时长

首先用aggregate按Customer.ID和Video.ID.v26分组,对Time.Spent.Watching求和,把重复的用户-视频记录合并成一条总时长记录:

# 聚合数据,得到每个用户每个视频的总观看时长
aggregated_time <- aggregate(
  Time.Spent.Watching ~ Customer.ID + Video.ID.v26,
  data = d2_cleaned,
  FUN = sum
)

这一步会把原来可能几十万条的记录压缩成“用户数×用户观看过的视频数”量级,直接减少后续处理的数据量。

第二步:把聚合数据转成宽格式(匹配目标表结构)

接下来需要把长格式的聚合数据转成和distinct_customers_after_cleaning一致的宽格式——每行一个用户,每列一个视频ID,值为对应总时长。这里用tidyr的pivot_wider或者reshape2的dcast都可以,我推荐tidyr(属于tidyverse生态,代码更直观):

library(tidyr)

# 转宽格式,未观看的视频自动填充0
wide_time <- pivot_wider(
  aggregated_time,
  id_cols = Customer.ID,          # 按用户ID分组
  names_from = Video.ID.v26,      # 把视频ID转成列名
  values_from = Time.Spent.Watching,  # 填充总时长
  values_fill = 0                 # 没有观看记录的视频填0
)

如果习惯用reshape2,代码是这样的:

library(reshape2)

wide_time <- dcast(
  aggregated_time,
  Customer.ID ~ Video.ID.v26,
  value.var = "Time.Spent.Watching",
  fill = 0
)

第三步:合并到目标表并填充数据

最后把宽格式的聚合数据和distinct_customers_after_cleaning合并,替换掉原来的0值。这里用dplyr的left_join配合coalesce来确保保留目标表的所有行和列:

library(dplyr)

# 合并数据,保留目标表的全部结构
final_df <- distinct_customers_after_cleaning %>%
  left_join(wide_time, by = "Customer.ID") %>%
  # 遍历所有视频列,用聚合后的时长替换原表的0(如果有匹配的话)
  mutate(
    across(
      names(.)[-c(1,2)],  # 排除前两列(用户ID和Hits列),处理所有视频列
      ~ coalesce(.x, .y),
      .y = cur_data_all()[cur_column()]
    )
  )

为什么原来的三重循环这么慢?

原来的三重循环是**O(n×m×k)**的时间复杂度:n是d2_cleaned的行数,m是用户数,k是视频列数——每一条观看记录都要遍历所有用户和所有视频列做判断,数据量大的时候完全不可行。

而我们的方法是O(n + m×k):先聚合把n条记录压缩成几百/几千条,再转宽格式,最后合并填充,相当于把最耗时的循环提前用R内置的向量运算完成(这些函数都是底层优化过的,比手写循环快N倍)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:02:29