我有一个如下所示的数据框:
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矩阵,该矩阵将包含一个标志,指示两个实体(行)之间是否存在匹配。
答案 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)
然后我们可以使用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
我们得到您想要的结果。