Obtaining connected components in R

前端 未结 1 1030
旧时难觅i
旧时难觅i 2020-12-17 21:16

I have a matrix with values 0 or 1 and I would like to obtain a list of groups of adjacent 1\'s.

For example, the matrix

mat = rbind(c(1,0,0,0,0),
          


        
相关标签:
1条回答
  • 2020-12-17 21:55

    With the update, you can turn your binary matrix into a raster object and use the clumps function. Then it is just data management to return the exact format you want. Example below:

    library(igraph)
    library(raster)
    
    mat = rbind(c(1,0,0,0,0),
                c(1,0,0,1,0),
                c(0,0,1,0,0),
                c(0,0,0,0,0),
                c(1,1,1,1,1))
    Rmat <- raster(mat)
    Clumps <- as.matrix(clump(Rmat, directions=4))
    
    #turn the clumps into a list
    tot <- max(Clumps, na.rm=TRUE)
    res <- vector("list",tot)
    for (i in 1:tot){
      res[i] <- list(which(Clumps == i, arr.ind = TRUE))
    }
    

    Which then res prints out at the console:

    > res
    [[1]]
         row col
    [1,]   1   1
    [2,]   2   1
    
    [[2]]
         row col
    [1,]   2   4
    
    [[3]]
         row col
    [1,]   3   3
    
    [[4]]
         row col
    [1,]   5   1
    [2,]   5   2
    [3,]   5   3
    [4,]   5   4
    [5,]   5   5
    

    I wouldn't be surprised if there is a better way to go from the raster object to your end goal though. Again a 2000 by 2000 matrix should not be a big deal for this.


    Old (wrong answer) but should be useful for people who want connected components of a graph.

    You can use the igraph package to turn your adjacency matrix into a network and return the components. Your example graph is one component, so I removed one edge for illustration.

    library(igraph)
    mat = rbind(c(1,0,0,0,0),
                c(1,0,0,1,0),
                c(0,0,1,0,0),
                c(0,0,0,0,0),
                c(1,1,1,1,1))
    g  <- graph.adjacency(mat) %>% delete_edges("5|3")
    plot(g)
    clu <- components(g)
    groups(clu)
    

    The final line then returns at the prompt:

    > groups(clu)
    $`1`
    [1] 1 2 4 5
    
    $`2`
    [1] 3
    

    My experience with this algorithm it is pretty fast - so I don't think 2,000 by 2,000 will be a problem.

    0 讨论(0)
提交回复
热议问题