如何根据R中的其他列/ id分配公共ID?

时间:2014-09-09 12:36:22

标签: r algorithm functional-programming network-programming

我有一个如下所示的数据框:

Sn  id1 id2 id3    
1   abc 123  NA   
2   xyz 111 vvv  
3   qwe 222 vvv    
4   rty  NA  NA    
5   abc  NA  NA    
6   ddd 234  NA   
7   sss 222  NA   
8   aaa  NA  NA

现在我想根据以下逻辑创建一个新列'output':

第一级关系:即使单个id匹配的所有实体(NA都不计算)也必须分配相同的id

第二级关系:如果2连接到3而3连接到7,那么2,3和7都必须具有相同的id

因此这里的输出将是:

Sn  id1 id2 id3 id4    
1   abc 123 NA  100001   
2   xyz 111 vvv 100002  
3   qwe 222 vvv 100002  
4   rty NA  NA  100003    
5   abc NA  NA  100001    
6   ddd 234 NA  100004    
7   sss 222 NA  100002   
8   aaa NA  NA  100005

请让我知道最简单的方法是什么。欢迎任何想法。

我目前正在考虑创建一个8 * 8矩阵,该矩阵将包含一个标志,指示两个实体(行)之间是否存在匹配。

1 个答案:

答案 0 :(得分:2)

我喜欢使用igraph执行此类任务(使用“已连接”节点)。因此,如果我们以复制/粘贴友好的data.frame格式开始您的样本数据

dd <- data.frame(
    Sn = 1:8, 
    id1 = c("abc", "xyz", "qwe", "rty", "abc", "ddd", "sss", "aaa"), 
    id2 = c(123L, 111L, 222L, NA, NA, 234L, 222L, NA), 
    id3 = c(NA, "vvv", "vvv", NA, NA, NA, NA, NA),
    stringsAsFactors=F
)

现在,第一步是在给定行的所有节点上构建边缘列表连接

el <- rbind(
    setNames(dd[,2:3], c("A","B")),
    setNames(dd[,3:4], c("A","B"))
)
el <- el[complete.cases(el),]    #(ignore NA)

我们还需要一个所有椎骨名称的唯一列表

vx <- na.omit(unique(unlist(dd[, 2:4])))

现在我们可以创建一个图形对象

library(igraph)
gg<-graph.data.frame(el, vertices=vx, directed=F)
plot(gg)

enter image description here

然后我们可以使用cluster()函数查找不同的组并获取每个顶点的组号

newid <- data.frame(
    vertex=V(gg)$name, 
    grp=clusters(gg)$membership
)

现在,如果我们想将其分配回原始data.frame,我们只需要匹配id1列。

dd$id4 <- newid$grp[match(dd$id1, newid$vertex)]+100000
dd

#   Sn id1 id2  id3    id4
# 1  1 abc 123 <NA> 100001
# 2  2 xyz 111  vvv 100002
# 3  3 qwe 222  vvv 100002
# 4  4 rty  NA <NA> 100003
# 5  5 abc  NA <NA> 100001
# 6  6 ddd 234 <NA> 100004
# 7  7 sss 222 <NA> 100002
# 8  8 aaa  NA <NA> 100005

我们得到您想要的结果。