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

如何用dplyr/tidyr将源表扩展为版本化历史状态表?

用dplyr生成用户动物信息的跟踪历史表

我希望基于源表生成一张「跟踪历史表」或「增量历史表」。源表示例如下:

library(tibble)

df_source <- 
  tibble::tribble(
  ~user_id, ~iteration,     ~animal, ~foo_val, ~bar_val,
     "xyz",         1L,     "zebra",      12L,       2L,
     "xyz",         1L,    "monkey",       3L,       4L,
     "xyz",         1L,  "elephant",       4L,      13L,
     "xyz",         2L,     "horse",      11L,       4L,
     "xyz",         2L,       "dog",       5L,      12L,
     "xyz",         2L,       "cow",       2L,      12L,
     "tty",         1L,   "giraffe",       8L,       4L,
     "tty",         1L,  "kangaroo",       6L,       1L,
     "tty",         1L,   "penguin",      12L,       5L,
     "tty",         2L, "crocodile",      10L,       7L,
     "tty",         2L,       "owl",       7L,       8L,
     "tty",         2L,  "kangaroo",      14L,       2L
  )

这里有两位用户,已知每位用户在各iteration中获取的animal信息。需要扩展该表,使其成为记录每个用户各iteration状态的历史表:

  • iteration 1仅保留该轮数据;
  • iteration 2需保留iteration 1和2的数据,若同一animal出现数据冲突,以iteration 2的版本为准。

预期结果需满足:

  1. 复制用户的上一轮iteration记录,将其status_as_of_iteration值递增
  2. 保留用户最新一轮iteration的记录不变

需注意:用户user_id为tty且status_as_of_iteration为2时,仅保留一条kangaroo记录,因为要为每个animal保留各iteration中的最新状态。

请问是否有使用dplyr或tidyr实现此需求的简便方法?


实现方法(基于dplyr)

可以通过分组、生成迭代范围、合并历史数据并去重的方式实现,核心思路是为每个用户的每一轮迭代,汇总截止到该轮的所有最新动物记录:

library(dplyr)

df_tracking <- df_source %>%
  # 按用户分组
  group_by(user_id) %>%
  # 为每个用户生成所有需要的迭代版本(1到最大iteration)
  mutate(status_as_of_iteration = list(1:max(iteration))) %>%
  # 展开每个迭代版本的记录
  unnest(status_as_of_iteration) %>%
  # 筛选出截止到当前status_as_of_iteration的所有记录
  filter(iteration <= status_as_of_iteration) %>%
  # 按用户、动物、状态迭代版本分组,保留每个动物在该迭代版本下的最新记录(最大iteration)
  group_by(user_id, animal, status_as_of_iteration) %>%
  slice_max(iteration, n = 1) %>%
  # 取消分组,整理结果
  ungroup() %>%
  # 按用户和状态迭代版本排序,让结果更清晰
  arrange(user_id, status_as_of_iteration, animal)

代码解释:

  • 分组与生成迭代范围:先按user_id分组,为每个用户生成从1到其最大iteration的序列,确保每个迭代版本都被覆盖。
  • 展开与筛选:将迭代范围展开后,筛选出所有早于等于当前status_as_of_iteration的记录,这样每个迭代版本都会包含之前所有轮次的数据。
  • 去重保留最新:按user_id、animal、status_as_of_iteration分组,用slice_max保留每个动物在该迭代版本下的最新(最大iteration)记录,解决冲突问题。
  • 排序整理:最后按用户和迭代版本排序,让结果更易读。

验证结果:

对于用户tty的status_as_of_iteration = 2,kangaroo只会保留iteration = 2的记录(foo_val=14,bar_val=2),完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:04:53