在访问矩阵的所有列组合时,如何避免双for循环?

在访问矩阵的所有列组合时,如何避免双for循环?,r,R,我一直试图在互联网上找到解决办法,但没有解决我的具体问题。 矩阵D告诉我一组矩形(列)的最大和最小x和y坐标。现在我想知道,其中一些相交的频率。我想到的评估两个列是否相交的方法需要遍历所有可能的列组合(也可以是“向后”)。现在对我来说,第一个直观的解决方案是将一个for循环通过列嵌套到另一个做同样事情的循环中。以下是一个例子: n <- 5 D <- matrix(c(1,2,1,2,1,3,1,3,2,4,2,4,3,5,1,2,3,4,2,4),nrow=4,ncol=n)

我一直试图在互联网上找到解决办法,但没有解决我的具体问题。 矩阵D告诉我一组矩形(列)的最大和最小x和y坐标。现在我想知道,其中一些相交的频率。我想到的评估两个列是否相交的方法需要遍历所有可能的列组合(也可以是“向后”)。现在对我来说,第一个直观的解决方案是将一个for循环通过列嵌套到另一个做同样事情的循环中。以下是一个例子:

n <- 5

D <- matrix(c(1,2,1,2,1,3,1,3,2,4,2,4,3,5,1,2,3,4,2,4),nrow=4,ncol=n)

E <- mat.or.vec(nr=n, nc=n)
for (i in 1:n){
    for (j in 1:n){
        if (i != j &&
           (D[1,i] <= D[1,j] & D[1,j] < D[2,i]) &&
           ((D[3,i] <= D[3,j] & D[3,j] < D[4,i]) | (D[3,i] < D[4,j] & D[4,j] <= D[4,i]))) { 
            E[i,j] <- 1
        }
    }
}

     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    0    0    0
[2,]    1    0    1    0    0
[3,]    0    0    0    0    1
[4,]    0    0    0    0    0
[5,]    0    0    0    0    0

我们看到,部分循环已经比完整循环有了显著的改进,但只比使用空间对象的解决方案稍好一点。因此,我决定采用罗兰解决方案。再次感谢

这不是我的专业领域,但您应该使用spatial软件包

library(sp)
library(rgeos)
n <- 5

D <- matrix(c(1,2,1,2,1,3,1,3,2,4,2,4,3,5,1,2,3,4,2,4),nrow=4,ncol=n)

D1 <- t(D)
D1 <- D1[, c(1, 3, 2, 3, 2, 4, 1, 4)]
ID <- paste0('rect', seq_len(nrow(D1)))

# Create SP
#http://stackoverflow.com/a/26620550/1412059
polys <- SpatialPolygons(mapply(function(poly, id) {
  xy <- matrix(poly, ncol=2, byrow=TRUE)
  Polygons(list(Polygon(xy)), ID=id)
}, split(D1, row(D1)), ID))

# Create SPDF
polys.df <- SpatialPolygonsDataFrame(polys, data.frame(id=ID, row.names=ID))

plot(polys.df, col=rainbow(50, alpha=0.5))
例如,
rect2
rect3
重叠,您尚未识别:

plot(polys.df[2:3,], col=rainbow(50, alpha=0.5))

还是它们互相包容

gContains(polys.df, byid = TRUE)
例如
rect2
包含
rect1

plot(polys.df[1:2,], col=rainbow(50, alpha=0.5))

等等

最后,您可以执行以下操作:

res <-  gOverlaps(polys.df, byid = TRUE) | 
        gContains(polys.df, byid = TRUE) | 
        gWithin(polys.df, byid = TRUE) | 
        gCovers(polys.df, byid = TRUE)
diag(res) <- 0

#      rect1 rect2 rect3 rect4 rect5
#rect1     0     1     0     0     0
#rect2     1     0     1     0     0
#rect3     0     1     0     0     1
#rect4     0     0     0     0     0
#rect5     0     0     1     0     0

res我喜欢罗兰的答案的原因有很多,而不是我将在这里给出的答案

  • 代码更能说明正在做什么。(六个月后,当您回到这里时,这一点非常重要)
  • 它更具概括性,适用于空间对象可以处理的任何形状
  • 它有很好的工具来说明这个问题
  • 尽管如此,我还是要提供一种可能比空间方法运行得更快的替代解决方案。但是,这仅适用于矩形

    首先,我们将依赖于一个逻辑测试,该测试基于。然后我们可以编写一个函数来执行这个测试,如下所示

    intersecting_rects <- function(edge1, edge2){
    #* index 1 is left edge, index 2 is right edge
    #* index 3 is lower edge, index 4 is upper edge
      (edge1[1] < edge2[2] && edge1[2] > edge2[1] &&
        edge1[3] < edge2[4] && edge1[4] > edge2[3])
    }
    
    还不错!但它与罗兰的答案相比如何呢?让我们把它全部设置好,并运行一个粗略的比较(主要警告:这个比较是在一组小得可笑的矩形上进行的,我不认为这会很好地扩展,但是如果你能在100个矩形上运行它,它应该会让你很好地了解什么是最快的)

    库(sp)
    图书馆(rgeos)
    图书馆(微基准)
    #*矩形比较函数
    相交直线边2[1]&&
    edge1[3]edge2[3])
    }
    
    n请提供一个最小的可复制示例。如果你有一个相对较小的矩形数,我会考虑给他们每个位字段,然后“油漆”(或)矩阵与他们。嗯,我有大约4000个,所以这是一个相对较小的数字?如果我错了,请纠正我,但<代码> e <代码>应该是一个对称矩阵,不是吗?也就是说,既然
    E[2,3]==1
    ,那么
    E[3,2]==1
    ?换句话说,当矩形2与矩形3相交时,矩形3不也与矩形2相交吗?我问的原因是,如果这是真的,你不需要在矩阵的全维上循环。你只需要做上矩阵或三角矩阵,它可以把你的循环一分为二。而且,
    for
    循环的名声不好。如果使用得当,它真的不是那么糟糕的工具<代码>for
    循环在必须重新评估所创建的对象类型,或用于生成不断扩展的对象时,性能往往最差。您已经预先定义了
    E
    的维度,并且没有更改其大小或类型,这一事实应该可以最大限度地减少与
    for
    循环相关的问题。我认为你必须非常有创意才能让某些东西运行得更快。我想我的答案对于大量多边形的缩放效果要好得多。也许OP可以用她的实际数据集进行基准测试。(对于创建我在粗略搜索中没有找到的空间多边形,可能还有更快的解决方案。)@Roland,我实际上对此有些怀疑,但这只是因为
    gOverlaps
    等中的逻辑被推广到了n边多边形。但我想这需要一个更大的实验来找出答案。正如本文的要点()所指出的,我需要一个更好的方式来度过我的周五早晨。为什么我觉得这些谜题如此有趣?总之,Gist创建了n个可以比较的矩形的随机集合。只要我的方法正确设置了矩形,我认为这是一个有效的比较。但是,如果我们不进行所有4个测试,我们可能会改进解决方案的时间安排。如果OP只需要一个方向的结果,前两个就足够了,例如三角形矩阵。嘿,多亏了你们两位,下周我回去工作时,我会尝试两种解决方案,并将结果发布在这里。但我已经可以说,我喜欢罗兰的答案是,它给了我一个很好的情节来检查我的计算是否有意义。
    res <-  gOverlaps(polys.df, byid = TRUE) | 
            gContains(polys.df, byid = TRUE) | 
            gWithin(polys.df, byid = TRUE) | 
            gCovers(polys.df, byid = TRUE)
    diag(res) <- 0
    
    #      rect1 rect2 rect3 rect4 rect5
    #rect1     0     1     0     0     0
    #rect2     1     0     1     0     0
    #rect3     0     1     0     0     1
    #rect4     0     0     0     0     0
    #rect5     0     0     1     0     0
    
    intersecting_rects <- function(edge1, edge2){
    #* index 1 is left edge, index 2 is right edge
    #* index 3 is lower edge, index 4 is upper edge
      (edge1[1] < edge2[2] && edge1[2] > edge2[1] &&
        edge1[3] < edge2[4] && edge1[4] > edge2[3])
    }
    
    n <- 5
    D <- matrix(c(1,2,1,2,1,3,1,3,2,4,2,4,3,5,1,2,3,4,2,4),nrow=4,ncol=n)
    
    E<-mat.or.vec(nr=n,nc=n)
    for (i in 1:n){
      for (j in (i:n)[-1]){
        E[i, j] <- as.numeric(intersecting_rects(D[, i], D[, j]))
      }
    }
    
    E[lower.tri(E)] <- t(E)[lower.tri(E)]
    E
    
    library(sp)
    library(rgeos)
    library(microbenchmark)
    
    #* Rectangles Comparison Function
    intersecting_rects <- function(edge1, edge2){
      (edge1[1] < edge2[2] && edge1[2] > edge2[1] &&
        edge1[3] < edge2[4] && edge1[4] > edge2[3])
    }
    
    n <- 5
    D <- matrix(c(1,2,1,2,1,3,1,3,2,4,2,4,3,5,1,2,3,4,2,4),nrow=4,ncol=n)
    
    
    #* Set up the Spatial Obects
    D1 <- t(D)
    D1 <- D1[, c(1, 3, 2, 3, 2, 4, 1, 4)]
    ID <- paste0('rect', seq_len(nrow(D1)))
    
        # Create SP
        #https://stackoverflow.com/a/26620550/1412059
    polys <- SpatialPolygons(mapply(function(poly, id) {
      xy <- matrix(poly, ncol=2, byrow=TRUE)
      Polygons(list(Polygon(xy)), ID=id)
    }, split(D1, row(D1)), ID))
    
        # Create SPDF
    polys.df <- SpatialPolygonsDataFrame(polys, data.frame(id=ID, row.names=ID))
    
    #* Benchmark the speeds
    microbenchmark(
      poly = {
        res <-  gOverlaps(polys.df, byid = TRUE) | 
                gContains(polys.df, byid = TRUE) | 
                gWithin(polys.df, byid = TRUE) | 
                gCovers(polys.df, byid = TRUE)
        diag(res) <- 0
      },
      full_loop = {
        E <- mat.or.vec(nr=n, nc=n)
        for (i in 1:n){
          for (j in 1:n){
            E[i, j] <- as.numeric(intersecting_rects(D[, i], D[, j]))
          }
        }
      },
      partial_loop = {
        E <- mat.or.vec(nr=n, nc=n)
        for (i in 1:n){
          for (j in (i:n)[-1]){
            E[i, j] <- as.numeric(intersecting_rects(D[, i], D[, j]))
          }
        }
        E[lower.tri(E)] <- t(E)[lower.tri(E)]
      }
    )
    
    Unit: microseconds
             expr      min        lq       mean    median        uq      max neval cld
             poly 2656.800 2720.8745 2812.72787 2767.2080 2811.4875 4200.736   100   b
        full_loop  108.795  116.5650  122.77029  120.8170  127.2690  175.947   100  a 
     partial_loop   69.500   76.3905   87.01193   85.7745   94.1325  166.857   100  a