如何利用行索引对在R中为数据框生成标识列?
问题描述
现有存储调查回复的数据框responses,定义如下:
responses <- data.frame(var1 = c(1,2,2,3,1,2,1), var2 = c("a","a","a","b","a","c","c")) responses # var1 var2 # 1 1 a # 2 2 a # 3 2 a # 4 3 b # 5 1 a # 6 2 c # 7 1 c
需要为responses添加id列,规则由数据框pairs定义:其中两列对应responses中应拥有相同id的行索引:
pairs <- data.frame(x=c(1,1,2,3), y=c(4,5,1,6)) pairs # x y # 1 1 4 # 2 1 5 # 3 2 1 # 4 3 6
期望输出中,行1、2、4、5共享id 1,行3、6共享id 2,行7为唯一id 3:
# var1 var2 id # 1 1 a 1 # 2 2 a 1 # 3 2 a 2 # 4 3 b 1 # 5 1 a 1 # 6 2 c 2 # 7 1 c 3
最简实现方法
这个问题本质是图的连通分量识别:把responses的每一行看作一个节点,pairs中的每一行(x,y)看作节点x和y之间的一条边,同一连通分量内的节点(行)应分配相同id。用igraph包可以高效解决这个问题:
步骤1:安装并加载igraph包(如果未安装)
install.packages("igraph") library(igraph)
步骤2:构建图并提取连通分量ID
# 将pairs转换为边列表,构建无向图 graph <- graph_from_data_frame(pairs, directed = FALSE) # 获取每个节点所属的连通分量编号 component_members <- components(graph)$membership
步骤3:将分量ID映射到所有行并整理
# 初始化id向量,默认每行id为自身行号 id_vec <- seq_len(nrow(responses)) # 替换已配对行的id为对应连通分量编号 id_vec[as.integer(names(component_members))] <- component_members # 重新编号,确保id从1开始连续递增 id_vec <- match(id_vec, unique(id_vec)) # 添加id列到responses responses$id <- id_vec
最终输出
运行上述代码后,responses将完全符合期望输出:
responses # var1 var2 id # 1 1 a 1 # 2 2 a 1 # 3 2 a 2 # 4 3 b 1 # 5 1 a 1 # 6 2 c 2 # 7 1 c 3
极简合并写法
如果想要更紧凑的代码,可以将步骤2和3合并:
library(igraph) resp_graph <- graph_from_data_frame(pairs, directed = FALSE) comp_ids <- components(resp_graph)$membership full_ids <- seq_len(nrow(responses)) full_ids[as.integer(names(comp_ids))] <- comp_ids responses$id <- match(full_ids, unique(full_ids))
内容的提问来源于stack exchange,提问作者James Martherus
相关产品推荐
相关产品推荐

