【问题标题】:Identifying "clusters" or "groups" in a matrix识别矩阵中的“簇”或“组”
【发布时间】:2014-06-27 15:33:51
【问题描述】:

我有一个填充了离散元素的矩阵,我需要将它们聚集成完整的组。因此,例如,采用这个矩阵:

[A B B C A]
[A A B A A]
[A B B C C]
[A A A A A]

A 有两个单独的集群,C 有两个单独的集群,B 有一个集群。

我正在寻找的输出理想情况下会为每个集群分配一个唯一的 ID,如下所示:

[1 2 2 3 4]
[1 1 2 4 4]
[1 2 2 5 5]
[1 1 1 1 1]

现在我有一个 R 代码,它通过迭代检查最近邻来递归地执行此操作,但是当矩阵变大(即 100x100)时它会迅速溢出。

R 中是否有内置函数可以做到这一点?我研究了光栅和图像处理,但没有运气。我确信它一定在那里。

谢谢!

【问题讨论】:

标签: r image-processing matrix cluster-computing


【解决方案1】:

您可以通过构建表示矩阵的格图来解决此问题,其中仅当顶点具有相同类型时才保留边:

# Build initial matrix and lattice graph
library(igraph)
mat <- matrix(c(1, 1, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1, 3, 1, 3, 1, 1, 1, 3, 1), nrow=4)
labels <- as.vector(mat)
g <- graph.lattice(dim(mat))
lyt <- layout.auto(g)

# Remove edges between elements of different types
edgelist <- get.edgelist(g)
retain <- labels[edgelist[,1]] == labels[edgelist[,2]]
g <- delete.edges(g, E(g)[!retain])

# Take a look at what we have
plot(g, layout=lyt)

顶点按列编号。很容易看出,我们需要做的就是抓取该图的组件:

matrix(clusters(g)$membership, nrow=nrow(mat))
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    2    2    3    4
# [2,]    1    1    2    4    4
# [3,]    1    2    2    5    5
# [4,]    1    1    1    1    1

如果您想在晶格中包含对角线,您可以从邻域大小为 2 的晶格开始,然后限制元素之间的距离不超过一行或一列。考虑以下矩阵:

[A B C B]
[B A A A]

由于包含对角链接,以下代码将捕获 4 个组,而不是 6 个:

# Build initial matrix and lattice graph (neighborhood size 2)
mat <- matrix(c(1, 2, 2, 1, 3, 1, 2, 1), nrow=2)
labels <- as.vector(mat)
rows <- (seq(length(labels)) - 1) %% nrow(mat)
cols <- ceiling(seq(length(labels)) / nrow(mat))
g <- graph.lattice(dim(mat), nei=2)

# Remove edges between elements of different types or that aren't diagonal
edgelist <- get.edgelist(g)
retain <- labels[edgelist[,1]] == labels[edgelist[,2]] &
  abs(rows[edgelist[,1]] - rows[edgelist[,2]]) <= 1 &
  abs(cols[edgelist[,1]] - cols[edgelist[,2]]) <= 1
g <- delete.edges(g, E(g)[!retain])

# Cluster to obtain final groups
matrix(clusters(g)$membership, nrow=nrow(mat))
#      [,1] [,2] [,3] [,4]
# [1,]    1    2    3    4
# [2,]    2    1    1    1

【讨论】:

  • 哇,太完美了。还有一个问题(因为我不熟悉 igraph 包)是否有一种快速的方法可以在不循环的情况下获取每个唯一组的组大小?因此,对于示例,组大小将是:组 1=9、组 2=5、组 3=1、组 4=3 和组 5=2
  • @user3037237 你可以使用table(clusters(g)$membership) 或clusters(g)$csize。
【解决方案2】:

我不太确定这是否解决了同样的问题,但我最近编写了一些代码,它以相同的方式将墙段分组在迷宫中,即最近邻。我的是迭代的,并利用 dist() 函数。这是我使用的一些代码。

我从一个包含所有墙段的 N*4 矩阵开始(使用 Prim 的树算法生成);列是 (x0,y0,x1,y1) 定义给定段的端点。所有段都在整数网格点上开始和结束,长度为 1。treelist 的每个元素都包含所有聚集的段。对于发布的问题,这应该更容易一些,因为每个项目只有一个坐标(行、列)而不是两个。

treelist<-list()
 treecnt<-1
 #kill edge walls, i.e. wall segments on the border of the maze.
 #  edges<- which(dowalls[,1]==dowalls[,3] | dowalls[,2]==dowalls[,4])
 vedges <- which( (dowalls[,1]==dowalls[,3]) & (dowalls[,1]==1 | dowalls[,1]==dimx+1) )
 hedges <- which( (dowalls[,2]==dowalls[,4]) & (dowalls[,2]==1 | dowalls[,1]==dimy+1) )
 dowalls<-dowalls[-c(vedges,hedges),,drop=FALSE]
 # now sort into trees 
 while(nrow(dowalls)>0 ) {
     tree <- matrix(dowalls[1,],nr=1) #force dimensions 
     dowalls<-dowalls[-1,,drop=FALSE]
     treerow <- 1 #current row of tree we're looking at
     while ( treerow <= nrow(tree) ) {
         #only examine the first 'column' of the dist() matrix 'cause those are the
         # distances from the tree[] endpoints
         touch <- c( which(dist(rbind(tree[treerow,1:2],dowalls[,1:2]) )[1:nrow(dowalls)]==0),  which(dist(rbind(tree[treerow,1:2],dowalls[,3:4]) )[1:nrow(dowalls)]==0), which(dist(rbind(tree[treerow,3:4],dowalls[,1:2]) )[1:nrow(dowalls)]==0), which(dist(rbind(tree[treerow,3:4],dowalls[,3:4]) )[1:nrow(dowalls)]==0) )
         if(length(touch) ) {
            tree <- rbind(tree,dowalls[c(touch),])
            dowalls <- dowalls[-c(touch),,drop=FALSE] 
            }
    # now be careful: want to track the row of tree[] we're working with AND
    # track how many rows there currently are in tree[]
        treerow <- treerow + 1 
    } #end of while treerow <= nrow 
    treelist[[treecnt]]<-tree
    treecnt <- treecnt + 1 
} #end ; all walls have been classified

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 1970-01-01
    • 2022-12-18
    • 2015-01-21
    • 1970-01-01
    • 2021-03-02
    相关资源
    最近更新 更多