簡體   English   中英

如何高效統計R中柵格像元周圍一定距離內的空間點數?

[英]How to efficiently count the number of spatial points within a certain distance around raster cells in R?

我想計算距離RasterLayer中 RasterLayer 的每個單元格一定距離內的( SpatialPointsDataFrame對象的)空間點數。結果值應替換該特定柵格單元格的原始值。 這是一個可重現的例子:

# load library
library(raster)

# generate raster
ras <- raster(nrow=18, ncol=36)
values(ras) <- NA

# create SpatialPointsDataFrame
x <- c(-160,-155,-153,-150, 30, -45, -44, -42, -40, 100, 110, 130)
y <- c(-75,-73,-71,-60, 0, 30, 35, 40, 41, 10, -10, 60)
z <- c(seq(1, 12, 1))
df <- data.frame(x,y,z)
spdf <- SpatialPointsDataFrame(coords=df[,c(1,2)],
                               data=as.data.frame(df[,3]), 
                               proj4string=CRS("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"))
# visualize
plot(ras)
plot(spdf, add=T)

# loop over all raster cells
for(r in 1:nrow(ras)){
  for(c in 1:ncol(ras)){
    # duplicate raster for subsequent modification
    ras_x <- ras
    # define cell for which to count the number of surrounding points
    ras_x[r,c] <- nrow(spdf) # some value that is impossible to be true, this is only a temporary placeholder
    ras_x[ras_x != nrow(spdf)] <- NA
    # convert raster cell to spatial point
    spatial_point <- rasterToPoints(ras_x, spatial=T)
    # calculate distance around raster cell
    ras_dist <- distanceFromPoints(ras_x, spatial_point)
    ras_dist <- ras_dist / 1000000 # scale values
    # define circular zone by setting distance threshold (raster only with values 1 or NA)
    ras_dist[ras_dist > 2] <- NA
    ras_dist[ras_dist <= 2] <- 1

    # create empty vector to count number of spatial points located within zone around the particular raster cell
    empty_vec <- c()
    # loop to check which value every point of SpatialPointsDataFrame corresponds to 
    for (i in 1:nrow(spdf)){
      point <- extract(ras_dist, spdf[i,])
      empty_vec[i] <- point
    }
    # sum of resulting vector is the number of points within surrounding zone around predefined raster cell
    val <- sum(na.omit(empty_vec))
    val
    ras[r,c] <- val

    # print for progress monitoring
    print(paste0("sum of points within radius around cell row ", r, " and column ", c, " is ", val))
    print(paste0("finished ", r, " out of ", nrow(ras)))
    print(paste0("finished ", c, " out of ", ncol(ras)))
    # both plots are just for visualization and progress monitoring
    plot(ras)
    plot(spdf, add=T)
  }
}

plot(ras)
plot(spdf, add=T)

在此處輸入圖像描述

生成的柵格正是我想要的,但我檢查SpatialPointsDataFrame的每個點的底層柵格值的方法似乎效率低下。 我的真實數據包括一個具有RasterLayer (nrow、ncol、ncell)的SpatialPointsDataFrame和一個具有 2664 個特征的 SpatialPointsDataFrame。 有沒有一種方法可以更有效地生成柵格,只需計算每個柵格單元周圍一定距離內有多少點?

如果您可以使用投影坐標,這可以通過 spatstat package 輕松完成。這需要您使用sf::st_transform()等來投影您的點(和網格),並且不會在全球范圍內工作。

加載 spatstat 並制作 2000 個隨機點來測試:

library(spatstat)
W <- square(1)
set.seed(42)
Y <- runifpoint(2000) # Random points in the unit square
plot(Y, main = "Random points in unit square")

制作 3000x3000 點網格(900 萬點):

xy <- gridcenters(W, 3000, 3000) # Grid of points in the unit square
X <- ppp(xy$x, xy$y, window = W, check = FALSE, checkdup = FALSE)

對於 900 萬個網格點中的每一個,計算半徑 0.01 內的其他點的數量(在我具有 16GB RAM 的速度相當快的筆記本電腦上計時):

system.time(counts <- crosspaircounts(X, Y, r = .01))
#>    user  system elapsed 
#>   1.700   0.228   1.928

轉換為 spatstat 的im格式(柵格類型格式——可以用 maptools 轉換)和 plot:

rslt <- as.im(data.frame(x = xy$x, y = xy$y, counts))
plot(rslt, main = "Point counts in raster cells")

疊加在計數上的點表明我們做了正確的事情:

plot(rslt, main = "Point counts in raster cells")
plot(Y, add = TRUE, col = rgb(1,1,1,.7), pch = 3)

我相信你也可以用raster做一些優雅而快速的事情,但我不是在那里問的合適人選。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM