R 确定链接在一起的多组关联事件
以链接ID的简单数据框为例:R 确定链接在一起的多组关联事件,r,grouping,identifier,linkage,R,Grouping,Identifier,Linkage,以链接ID的简单数据框为例: test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11)) > test id1 id2 1 10 1 2 10 36 3 1 24 4 1 45 5 24 300 6 8 11 现在我大致知道了我想要的逻辑,但不知道如何优雅地实现它。我正在考虑在%中递归使用match或%in%来遍历每个分支,但这次我真的被难倒了 我要追求的最终结果是: re
test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11))
> test
id1 id2
1 10 1
2 10 36
3 1 24
4 1 45
5 24 300
6 8 11
现在我大致知道了我想要的逻辑,但不知道如何优雅地实现它。我正在考虑在%中递归使用match
或%in%
来遍历每个分支,但这次我真的被难倒了
我要追求的最终结果是:
result <- data.frame(group=c(1,1,1,1,1,1,2,2),id=c(10,1,24,36,45,300,8,11))
> result
group id
1 1 10
2 1 1
3 1 24
4 1 36
5 1 45
6 1 300
7 2 8
8 2 11
结果
组id
1 1 10
2 1 1
3 1 24
4 1 36
5 1 45
6 1 300
7 2 8
8 2 11
Bioconductor包RBGL(BOOST图形库的R接口)包含
一个函数,connectedComp()
,用于标识图形中连接的组件--
正是你想要的
(要使用该功能,您首先需要安装可用和可用的graph和RBGL软件包。)
库(RBGL)
测试这里有一个替代答案,是我在Josh向正确方向轻推后发现的。此答案使用igraph
软件包。
对于那些正在搜索并找到这个答案的人,我的测试数据集在图论中被称为“边列表”或“邻接列表”()
库(igraph)
不使用包装进行测试:
# 2 sets of test data
mytest <- data.frame(id1=c(10,10,3,1,1,24,8,11,32,11,45),id2=c(1,36,50,24,45,300,11,8,32,12,49))
test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11))
grouppairs <- function(df){
# from wide to long format; assumes df is 2 columns of related id's
test <- data.frame(group = 1:nrow(df),val = unlist(df))
# keep moving to next pair until all same values have same group
i <- 0
while(any(duplicated(unique(test)$val))){
i <- i+1
# get group of matching values
matches <- test[test$val == test$val[i],'group']
# change all groups with matching values to same group
test[test$group %in% matches,'group'] <- test$group[i]
}
# renumber starting from 1 and show only unique values in group order
test$group <- match(test$group, sort(unique(test$group)))
unique(test)[order(unique(test)$group), ]
}
# test
grouppairs(test)
grouppairs(mytest)
#2组测试数据
我的测试你说的是递归。。。我想我在做的时候会非常简洁
测试数据
mytest <- data.frame(id1=c(10,10,3,1,1,24,8,11,32,11,45),id2=c(1,36,50,24,45,300,11,8,32,12,49))
test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11))
aveminrec()可能与您的想法一致,不过我敢打赌,有一种方法可以更直接地遍历每个分支,而不是重复ave(),它本质上是split()和lappy()。也许是递归拆分和重叠?实际上,它就像重复的部分分支,或者交替地稍微简化2个向量,而不丢失组信息
也许其中的一部分可以用于解决实际问题,但groupvalues()太密集了,至少在没有注释的情况下无法阅读。我还没有检查性能与使用ave的for循环以及以这种方式翻转组相比如何。谢谢您的回答。在搜索更多信息时,我现在还可以使用“连接组件”一词。很高兴能够为您指出一条有用的途径。干杯祝你快乐。我刚刚测试了这个答案,链接和包确实成功了,就像九年前一样。我希望如此,而这个问题在25年前,当我和SAS试图解决这个问题时,我的头撞在墙上。@bondeddust-巧合的是,这个问题是由于试图替换一个丑陋的还有一段低效的SAS代码做了类似的事情。现在我忘记了这个问题和答案,但最近的邮件@HenrikHi@提醒我了!我认为graph.data.frame
被graph\u from\u data\u frame
取代,而clusters
由组件组成。至少当我?
使用这些函数时,我会被重定向到这些函数。类似的欢呼声R中有一个名为Recall
的函数,据说它改进了基于递归的代码。而ave
可以被认为是lapply
和split
的简单捆绑,但它实际上不能处理分组中多个列的操作。
library(igraph)
test <- data.frame(id1=c(10,10,1,1,24,8 ),id2=c(1,36,24,45,300,11))
gr.test <- graph_from_data_frame(test)
links <- data.frame(id=unique(unlist(test)),group=components(gr.test)$membership)
links[order(links$group),]
# id group
#1 10 1
#2 1 1
#3 24 1
#5 36 1
#6 45 1
#7 300 1
#4 8 2
#8 11 2
# 2 sets of test data
mytest <- data.frame(id1=c(10,10,3,1,1,24,8,11,32,11,45),id2=c(1,36,50,24,45,300,11,8,32,12,49))
test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11))
grouppairs <- function(df){
# from wide to long format; assumes df is 2 columns of related id's
test <- data.frame(group = 1:nrow(df),val = unlist(df))
# keep moving to next pair until all same values have same group
i <- 0
while(any(duplicated(unique(test)$val))){
i <- i+1
# get group of matching values
matches <- test[test$val == test$val[i],'group']
# change all groups with matching values to same group
test[test$group %in% matches,'group'] <- test$group[i]
}
# renumber starting from 1 and show only unique values in group order
test$group <- match(test$group, sort(unique(test$group)))
unique(test)[order(unique(test)$group), ]
}
# test
grouppairs(test)
grouppairs(mytest)
mytest <- data.frame(id1=c(10,10,3,1,1,24,8,11,32,11,45),id2=c(1,36,50,24,45,300,11,8,32,12,49))
test <- data.frame(id1=c(10,10,1,1,24,8),id2=c(1,36,24,45,300,11))
aveminrec <- function(v1,v2){
v2 <- ave(v1,by = v2,FUN = min)
if(identical(v1,v2)){
as.numeric(as.factor(v2))
}else{
aveminrec(v2,v1)
}
}
groupvalues <- function(valuepairs){
val <- unlist(valuepairs)
grp <- aveminrec(val,1:nrow(valuepairs))
unique(data.frame(grp,val)[order(grp,val), ])
}
groupvalues(test)
groupvalues(mytest)