我有一组对。每一对表示为[i,1:2]
。也就是说,ith
对是ith
行第一列和第二列的数字。
我需要将这些对排序到不同的组中,s.t. jth
组中任何对中的元素都不属于j
以外的任何组。例如:
> col1 <- c(3, 4, 6, 7, 10, 8)
> col2 <- c(6, 7, 3, 4, 3, 1)
>
> dat <- cbind(col1, col2)
> rownames(dat) <- 1:nrow(dat)
>
> dat
col1 col2
1 3 6
2 4 7
3 6 3
4 7 4
5 10 3
6 8 1
对于所有的对,无论数字在第一列还是第二列,都应该将它们分成组,每组中每对中的每一个数字只存在于一个组中。所以解出的例子是这样的。
col1 col2 groups
1 3 6 1
2 4 7 2
3 6 3 1
4 7 4 2
5 10 3 1
6 8 1 3
第1、3和5行被分组在一起,因为1和3包含相同的数字,并且5共享数字3,所以它必须与它们分组。2和4有相同的不同的数字,所以它们被分组在一起,6有唯一的数字,所以它被单独留下。
如果我们稍微改变数据,请注意以下内容:
示例2:新建数据请注意当我们添加与第6行和第5行共享元素的行时会发生什么。
col1 col2 groups
1 3 6 1
2 4 7 2
3 6 3 1
4 7 4 2
5 10 3 1
6 8 1 1
7 1 10 1
第7行的10
将它连接到第1组,因为它与第5行共享一个元素。它还与第6行共享一个元素(数字1
),因此第6行将在第1组中。
是否有一种简单的方法来形成组?矢量运算?排序算法?如果您尝试使用循环来执行此操作,那么很快就会变得非常糟糕,因为后续的每一行都可以更改前一行的成员关系,如示例中所示。
要利用旧的答案:识别链接在一起的剧集组,它为每个单独的值分配一个组,您可以尝试为每个链接对分配一个组:
library(igraph)
g <- graph_from_data_frame(dat)
links <- data.frame(col1=V(g)$name,group=components(g)$membership)
merge(dat,links,by="col1",all.x=TRUE,sort=FALSE)
# col1 col2 group
#1 3 6 1
#2 4 7 2
#3 6 3 1
#4 7 4 2
#5 10 3 1
#6 8 1 3
你的元素可以被视为无向图中的顶点,你的对可以被视为边,然后(假设你想找到最小大小的组——如果你不这样做,那么例如,整个组对可以被标记为"组1")你正在寻找的组是这个图中的连接组件。它们都可以在线性时间内通过深度优先或宽度优先的搜索找到。