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

在R中按id分组计算行间文本列的两类唯一差异

按ID分组计算行间文本唯一差异(Tidyverse方案)

我有一个按id和time排序的数据框,每行包含一个文本列。需要按id分组完成两类行间文本唯一差异计算:

  • 当前行与上一行的文本唯一差异及差异数量
  • 当前行与之前所有行的文本唯一差异及差异数量

下方是示例数据(包含输入列及期望输出的第4至7列),优先采用tidyverse解决方案。

编辑说明:数据已整理干净

# 示例数据
df <- structure(list(id = c(1, 1, 1, 2, 2, 2, 3, 3, 3), time = c(1, 
2, 3, 1, 2, 3, 1, 2, 3), input = c("Item 1,Item 2,Item 3,Item 4", 
"Item 1,Item 3,Item 5", "Item 1,Item 2,Item 3,Item 4", "Item 7,Item 4,Item 8", 
"Item 12,Item 20,Item 30", "Item 12,Item 20,Item 30,Item 4,Item 8", 
"A,B,C,D", "C,D,E,F", "A,B,C,D,E,F"), new_items = c(NA, "Item 5", 
"Item 2, Item 4", NA, "Item 12,Item 20,Item 30", "Item 4, Item 8", 
NA, "E,F", "A,B"), num_of_new_items = c(0, 1, 2, 0, 3, 2, 0, 
2, 2), new_items_overall = c(NA, "Item 5", NA, NA, "Item 12,Item 20,Item 30", 
NA, NA, "E, F", NA), num_of_new_items_overall = c(0, 1, 0, 0, 
3, 0, 0, 2, 0)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-9L))

解决方案

library(tidyverse)

result <- df %>%
  group_by(id) %>%
  # 将输入文本拆分为去重的元素集合
  mutate(current_set = str_split(input, ",") %>% map(trimws) %>% map(set)) %>%
  # 计算当前行与上一行的差异
  mutate(
    prev_set = lag(current_set),
    new_items = if_else(row_number() == 1, 
                       NA_character_,
                       map2_chr(current_set, prev_set, ~{
                         diff <- setdiff(.x, .y)
                         if(length(diff) == 0) NA_character_ else str_c(diff, collapse = ", ")
                       })),
    num_of_new_items = if_else(row_number() == 1, 
                               0,
                               map2_int(current_set, prev_set, ~length(setdiff(.x, .y))))
  ) %>%
  # 计算当前行与之前所有行的差异
  mutate(
    # 累积合并之前所有行的元素集合
    all_prev_sets = accumulate(lag(current_set), ~union(.x, .y), .init = list()),
    all_prev_set = map(all_prev_sets, ~reduce(.x, union)),
    new_items_overall = if_else(row_number() == 1, 
                                NA_character_,
                                map2_chr(current_set, all_prev_set, ~{
                                  diff <- setdiff(.x, .y)
                                  if(length(diff) == 0) NA_character_ else str_c(diff, collapse = ", ")
                                })),
    num_of_new_items_overall = if_else(row_number() == 1, 
                                       0,
                                       map2_int(current_set, all_prev_set, ~length(setdiff(.x, .y))))
  ) %>%
  # 移除中间辅助列
  select(-current_set, -prev_set, -all_prev_sets, -all_prev_set) %>%
  ungroup()

# 查看结果
print(result)

代码说明

  1. 文本拆分与集合转换:将每行的input文本按逗号拆分、去空格后转为集合,方便后续集合运算
  2. 与上一行的差异计算:用lag()获取上一行的元素集合,通过setdiff()提取当前行独有的元素,再合并为字符串并统计数量
  3. 与之前所有行的差异计算:用accumulate()累积合并之前所有行的元素集合得到总并集,再通过setdiff()提取当前行独有的元素,合并为字符串并统计数量
  4. 最终移除中间辅助列,得到与示例输出完全匹配的结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:52:52