R 更有效地覆盖多边形或从空间线提取()光栅数据

R 更有效地覆盖多边形或从空间线提取()光栅数据,r,overlay,extract,gis,R,Overlay,Extract,Gis,我有一个包含15亿条空间线的庞大数据集,我使用37000个点的所有组合创建了该数据集对于每一条空间线,我想提取线接触到的多边形(或光栅-任何更快的)的最大值。本质上这是一个非常大的“空间连接”,用圆弧术语来说。如果在多边形层上叠加线,则输出将是所有属性字段中空间线的最大值,每个属性字段表示一年中的一个月。我还包括了一个光栅数据集,它是从1990年1月的多边形文件中创建的,分辨率约为30米-光栅代表了一种我认为可能节省时间的替代方法。多边形和光栅层表示一个大的空间区域:大约30km x 10km。

我有一个包含15亿条空间线的庞大数据集,我使用37000个点的所有组合创建了该数据集对于每一条空间线,我想提取线接触到的多边形(或光栅-任何更快的)的最大值。本质上这是一个非常大的“空间连接”,用圆弧术语来说。如果在多边形层上叠加线,则输出将是所有属性字段中空间线的最大值,每个属性字段表示一年中的一个月。我还包括了一个光栅数据集,它是从1990年1月的多边形文件中创建的,分辨率约为30米-光栅代表了一种我认为可能节省时间的替代方法。多边形和光栅层表示一个大的空间区域:大约30km x 10km。数据是可用的。我在.zip中包含的空间线数据集只有9900条线,是从15亿条线的整个数据集中随机抽样的

首先读入数据

#polygons

 poly<-readShapePoly("ls_polys_bin",proj4string=CRS("+proj=utm +zone=21 +south +datum=WGS84 +units=m +no_defs"))
 poly$SP_ID<-NULL #deleting this extra field in prep for overlay

#raster - this represents only one month (january 1990)
   #raster created from polygon layer but one month only

     raster.jan90<-readGDAL("rast_jan90.tif") 
     raster.jan90<-raster(raster.jan90) #makes it into a raster

#lines (9900 of 1.5 billion included)

     lines<-readShapeLines("l_spatial",proj4string=CRS("+proj=utm +zone=21 +south +datum=WGS84 +units=m +no_defs"))
首先,我尝试了覆盖,但以目前的速度,整个15亿数据集在我的机器上运行大约需要844天

 ptm <- proc.time() #start clock
 overlays.all<-over(lines.50,poly, fn=max)
 ptm.sec.overlay<-proc.time() - ptm # stop clock
 ptm.sec.overlay #.56 sec w/ n=12 lines; 2.3 sec w/ 50 lines

ptm我认为最快的方法是将线光栅化为与光栅数据相同的光栅

但是,我不会在R中对它们进行光栅化。我会编写一些C代码,获取光栅和37000点位置的数据,然后使用Bresenham线条绘制算法获得线条的光栅位置。在这些位置对光栅进行采样,然后根据需要对这些数据执行任何操作。Bresenham算法的快速代码应该很容易获得,您甚至可以找到在GPU上运行的版本,以实现大规模加速。有什么比图形卡画直线快

我假设你的空间线是两点之间的直线段

或者,只需从亚马逊(或其他云服务提供商)租用1000台服务器,为期半天

这里有一个技巧,可以给出一个很好的近似值。它可能会得到改进(getCrds需要很多时间),包括采取更大的步骤(我不知道这对您是否合适)

库(光栅)
raster.jan90所有37000点对(不包括零长度线A-A)应仅提供684481500条线进行检查,因为A-B与B-A命中相同的多边形。因此,这是422天。。。
plot(raster.jan90)#where green=1
plot(poly, axes=T,cex.axis=0.75, add=T)
plot(lines.50, col="red", add=TRUE)
 ptm <- proc.time() #start clock
 overlays.all<-over(lines.50,poly, fn=max)
 ptm.sec.overlay<-proc.time() - ptm # stop clock
 ptm.sec.overlay #.56 sec w/ n=12 lines; 2.3 sec w/ 50 lines
 ptm <- proc.time() # Start clock
 ext.rast.jan90<-extract(raster.jan90,lines.50, fun=max, method=simple)
 ptm.sec.ext<-proc.time() - ptm # stop clock
 ptm.sec.ext #32 sec w/ n=12 lines; 191 sec w/ n=50 lines
library(raster)
raster.jan90 <- raster("rast_jan90.tif") 
lines <- shapefile("l_spatial.shp", p4s="+proj=utm +zone=21 +south +datum=WGS84 +units=m +no_defs")  
lines.50<-lines[sample(nrow(lines),50),]

test <- function(lns) {

  getCrds <- function(i) {
    p <- z[[i]][[1]]
    s <- (p[2,] - p[1,]) / res(raster.jan90)
    step <- round(max(abs(s)))
    if ( step < 1 ) {
        # these probably should not exist, but they do
        return( cbind(i, cellFromXY(raster.jan90, p[1, , drop=FALSE])) )
    }
    x <- seq(p[1,1], p[2,1], length.out=step)
    y <- seq(p[1,2], p[2,2], length.out=step)
    cbind(i, unique(cellFromXY(raster.jan90, cbind(x, y))))
  }

  z <- coordinates(lns)
  crd <- sapply(1:length(z), getCrds )
  crd <- do.call(rbind, crd)

  e <- extract(raster.jan90, crd[, 2])
  tapply(e, crd[,1], max)
}

system.time(res <- test(lines.50))
#  user  system elapsed 
#  0.53    0.01    0.55 

system.time(res <- test(lines))
#  user  system elapsed 
#  59.72    0.85   60.58