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

如何在dplyr中按ID、ADDRESS及NAME_1/NAME_2任一相同项分组?

解决方案:基于ID/ADDRESS分组后,按NAME关联生成GRP标识

要实现需求,需要先按ID和ADDRESS分组,再在每个分组内识别NAME_1与NAME_2的连通关联(即共享任意NAME的行归为同一组),最后生成全局唯一的GRP编号。可以结合dplyr和igraph包完成这个逻辑:

library(dplyr)
library(igraph)

# 示例输入数据
df <- data.frame(
  ID = c("1234", "1234", "1234", "1234", "1234", "1234", "2345"),
  ADDRESS = c("Weg 1", "Weg 1", "Weg 1", "Weg 1", "Weg 1", "Weg 1", "Weg 1234"),
  NAME_1 = c("Müller", "Peter", "Hirn", "Hirn", "Test", "Test", "Müller"),
  NAME_2 = c("Meier", "Meier", "Mensch", "Maler", "Hallo", "Velo", "Meier")
)

# 生成GRP列的逻辑
result_df <- df %>%
  group_by(ID, ADDRESS) %>%
  mutate(
    # 为当前分组创建NAME的边列表
    edges = list(tibble(from = NAME_1, to = NAME_2)),
    # 构建图并获取每个NAME的连通组件编号
    comps = list(
      edges[[1]] %>%
        graph_from_data_frame(directed = FALSE) %>%
        components() %>%
        .$membership
    ),
    # 为每行分配组件编号(取NAME_1对应的组件即可,同一行的两个NAME必属同一组件)
    local_grp = comps[[1]][as.character(NAME_1)]
  ) %>%
  ungroup() %>%
  # 将局部组件编号转换为全局唯一的GRP
  mutate(GRP = dense_rank(paste(ID, ADDRESS, local_grp, sep = "_"))) %>%
  # 清理临时列
  select(-edges, -comps, -local_grp)

# 查看结果
print(result_df)

代码逻辑说明

  1. 基础分组:先按ID和ADDRESS分组,确保只在同一地址和ID的范围内处理NAME关联。
  2. 构建连通图:将每个分组内的NAME_1和NAME_2视为图的边,用igraph创建无向图,识别连通组件(即共享NAME的节点会被归为同一组件)。
  3. 映射组件编号:将每个NAME对应的组件编号映射回原数据行,得到分组内的局部组号。
  4. 全局GRP生成:用dense_rank将ID+ADDRESS+局部组号的组合转换为连续的全局唯一GRP编号。

运行后得到的结果与示例期望输出完全一致:

# A tibble: 7 × 5
  ID    ADDRESS NAME_1 NAME_2   GRP
  <chr> <chr>   <chr>  <chr>  <int>
1 1234  Weg 1   Müller Meier      1
2 1234  Weg 1   Peter  Meier      1
3 1234  Weg 1   Hirn   Mensch     2
4 1234  Weg 1   Hirn   Maler      2
5 1234  Weg 1   Test   Hallo      3
6 1234  Weg 1   Test   Velo       3
7 2345  Weg 1234 Müller Meier      4

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:49:51