如何在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)
代码逻辑说明
- 基础分组:先按
ID和ADDRESS分组,确保只在同一地址和ID的范围内处理NAME关联。 - 构建连通图:将每个分组内的
NAME_1和NAME_2视为图的边,用igraph创建无向图,识别连通组件(即共享NAME的节点会被归为同一组件)。 - 映射组件编号:将每个NAME对应的组件编号映射回原数据行,得到分组内的局部组号。
- 全局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
相关产品推荐
相关产品推荐

