Tính khoảng cách {tối thiểu} giữa các đa giác trong R


9

Tôi đã tính diện tích bề mặt của các phân bố loài (hợp nhất đa giác từ shapefile), nhưng vì khu vực này có thể bao gồm các đa giác khá xa, tôi muốn tính toán một số biện pháp phân tán. Những gì tôi đã làm cho đến nay là lấy ra các tâm của mỗi đa giác, tính khoảng cách giữa chúng và sử dụng chúng để tính hệ số biến đổi, như trong ví dụ giả dưới đây;

require(sp)
require(ggplot2)
require(mapdata)
require(gridExtra)
require(scales)
require(rgeos)
require(spatstat)

# Create the coordinates for 3 squares
ls.coords <- list()
ls.coords <- list()
ls.coords[[1]] <- c(15.7, 42.3, # a list of coordinates
                    16.7, 42.3,
                    16.7, 41.6,
                    15.7, 41.6,
                    15.7, 42.3)

ls.coords[[2]] <- ls.coords[[1]]+0.5 # use simple offset

ls.coords[[3]] <- c(13.8, 45.4, # a list of coordinates
                    15.6, 45.4,
                    15.6, 43.7,
                    13.8, 43.7,
                    13.8, 45.4)

# Prepare lists to receive the sp objects and data frames
ls.polys <- list()
ls.sp.polys <- list()

for (ii in seq_along(ls.coords)) {
   crs.args <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
   my.rows <- length(ls.coords[[ii]])/2
   # create matrix of pairs
   my.coords <- matrix(ls.coords[[ii]],nrow = my.rows,ncol = 2,byrow = TRUE)
   # now build sp objects from scratch...
   poly = Polygon(my.coords)
   # layer by layer...
   polys = Polygons(list(poly),1)
   spolys = SpatialPolygons(list(polys))
   # projection is important
   proj4string(spolys) <- crs.args
   # Now save sp objects for later use
   ls.sp.polys[[ii]] <- spolys
   # Then create data frames for ggplot()
   poly.df <- fortify(spolys)
   poly.df$id <- ii
   ls.polys[[ii]] <- poly.df
}

# Convert the list of polygons to a list of owins
w <- lapply(ls.sp.polys, as.owin)
# Calculate the centroids and get the output to a matrix
centroid <- lapply(w, centroid.owin)
centroid <- lapply(centroid, rbind)
centroid <- lapply(centroid, function(x) rbind(unlist(x)))
centroid <- do.call('rbind', centroid)

# Create a new df and use fortify for ggplot
centroid_df <- fortify(as.data.frame(centroid))
# Add a group column
centroid_df$V3 <- rownames(centroid_df)

ggplot(data = italy, aes(x = long, y = lat, group = group)) +
  geom_polygon(fill = "grey50") +
  # Constrain the scale to 'zoom in'
  coord_cartesian(xlim = c(13, 19), ylim = c(41, 46)) +
  geom_polygon(data = ls.polys[[1]], aes(x = long, y = lat, group = group), fill = alpha("red", 0.3)) +
  geom_polygon(data = ls.polys[[2]], aes(x = long, y = lat, group = group), fill = alpha("green", 0.3)) +
  geom_polygon(data = ls.polys[[3]], aes(x = long, y = lat, group = group), fill = alpha("lightblue", 0.8)) + 
  coord_equal() +
  # Plot the centroids
  geom_point(data=centroid_points, aes(x = V1, y = V2, group = V3))

# Calculate the centroid distances using spDists {sp}
centroid_dists <- spDists(x=centroid, y=centroid, longlat=TRUE)

centroid_dists

       [,1]      [,2]     [,3]
[1,]   0.00000  69.16756 313.2383
[2,]  69.16756   0.00000 283.7120
[3,] 313.23834 283.71202   0.0000

# Calculate the coefficient of variation as a measure of polygon dispersion 
cv <- sd(centroid_dist)/mean(centroid_dist)
[1] 0.9835782

Âm mưu của ba đa giác và trọng tâm của họ

nhập mô tả hình ảnh ở đây

Tôi không chắc cách tiếp cận này có hữu ích hay không vì trong nhiều trường hợp, một số đa giác (như màu xanh trong ví dụ trên) khá lớn so với phần còn lại, do đó làm tăng khoảng cách hơn nữa. Ví dụ, trung tâm của Úc có khoảng cách gần như tương đương với nội trú phía tây so với Papau.

Những gì tôi muốn nhận được là một số đầu vào về phương pháp thay thế. Ví dụ, làm thế nào hoặc với chức năng nào tôi có thể tính khoảng cách giữa các đa giác?

Tôi đã thử nghiệm để chuyển đổi khung dữ liệu SpatialPolygon ở trên thành PointPotypes (ppp) {spatstat}để có thể chạy nndist() {spatstat}để tính khoảng cách giữa tất cả các điểm. Nhưng vì tôi đang xử lý các khu vực khá lớn (nhiều đa giác và lớn), ma trận trở nên rất lớn và tôi không biết làm thế nào để tiếp tục đạt được khoảng cách tối thiểu giữa các đa giác .

Tôi cũng đã xem xét chức năng gDistance {rgeos}, nhưng tôi nghĩ rằng nó chỉ hoạt động trên dữ liệu dự kiến ​​có thể là một vấn đề đối với tôi vì các khu vực của tôi có thể đi qua một số EPSG areas. Vấn đề tương tự sẽ phát sinh cho chức năng crossdist {spatstat}.


1
Bạn sẽ xem xét sử dụng postgres/postgisngoài R? Tôi đã sử dụng một quy trình công việc trong đó tôi thực hiện phần lớn công việc của mình R, nhưng lưu trữ dữ liệu trong cơ sở dữ liệu mà tôi truy cập bằng cách sử dụng sqldf. Điều này cho phép bạn sử dụng tất cả các postgischức năng (trong đó khoảng cách giữa các đa giác là đơn giản)
djq

@djq: Cảm ơn đã bình luận. Vâng, tôi chắc chắn sẽ thử nó :) Tôi bắt đầu xây dựng cơ sở dữ liệu postgresnhưng đã dừng lại khi tôi không biết (không nhìn) cách kết nối luồng công việc / geostats giữa cơ sở dữ liệu và R...
jO.

Câu trả lời:


9

Bạn có thể thực hiện phân tích này trong gói "spdep". Trong các hàm lân cận có liên quan, nếu bạn sử dụng "longlat = TRUE", hàm sẽ tính khoảng cách vòng tròn lớn và trả về km dưới dạng đơn vị khoảng cách. Trong ví dụ dưới đây, bạn có thể ép đối tượng danh sách khoảng cách kết quả ("dist.list") thành ma trận hoặc data.frame, tuy nhiên, việc tính toán thống kê tóm tắt khá hiệu quả bằng cách sử dụng lapply.

require(sp)
require(spdep)

# Create SpatialPolygonsDataFrame for 3 squares
poly1 <- Polygons(list(Polygon(matrix(c(15.7,42.3,16.7,42.3,16.7,41.6,15.7,41.6,15.7,42.3), 
                   nrow=5, ncol=2, byrow=TRUE))),"1")     
poly2 <- Polygons(list(Polygon(matrix(c(15.7,42.3,16.7,42.3,16.7,41.6,15.7,41.6,15.7,42.3)+0.5, 
                   nrow=5, ncol=2, byrow=TRUE))),"2")     
poly3 <- Polygons(list(Polygon(matrix(c(13.8, 45.4, 15.6, 45.4,15.6, 43.7,13.8, 43.7,13.8, 45.4), 
                   nrow=5, ncol=2, byrow=TRUE))),"3")                      
spolys = SpatialPolygons(list(poly1,poly2,poly3),1:3)
 spolys <- SpatialPolygonsDataFrame(spolys, data.frame(ID=sapply(slot(spolys, "polygons"), 
                                    function(x) slot(x, "ID"))) )   
   proj4string(spolys) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"

# Centroid coordinates (not used but provided for example) 
coords <- coordinates(spolys)

# Create K Nearest Neighbor list
skNN.nb <- knn2nb(knearneigh(coordinates(spolys), longlat=TRUE), 
                  row.names=spolys@data$ID)

# Calculate maximum distance for all linkages 
maxDist <- max(unlist(nbdists(skNN.nb, coordinates(spolys), longlat=TRUE)))

# Create spdep distance object
sDist <- dnearneigh(coordinates(spolys), 0, maxDist^2, row.names=spolys@data$ID)
  summary(sDist, coordinates(spolys), longlat=TRUE)

# Plot neighbor linkages                  
plot(spolys, border="grey") 
  plot(sDist, coordinates(spolys), add=TRUE)  

# Create neighbor distance list 
( dist.list <- nbdists(sDist, coordinates(spolys), longlat=TRUE) )

# Minimum distance 
( dist.min <- lapply(dist.list, FUN=min) )

# Distance coefficient of variation    
( dist.cv <- lapply(dist.list, FUN=function(x) { sd(x) / mean(x) } ) )

Cảm ơn đã bình luận và cái nhìn sâu sắc vào spdebgói. Chỉ cần làm rõ, cách tiếp cận này mang lại đầu ra giống như trong ví dụ của tôi, phải không?
jO.

Chỉ trong trường hợp bạn không thấy bình luận trên của tôi
jO.

Mặc dù phản hồi cung cấp mã hữu ích để tính khoảng cách giữa các nhân, nhưng nó không xử lý điểm trung tâm của OP, đó là cách tìm khoảng cách giữa hai điểm gần nhất của đường viền đa giác.
csfowler

Một cảnh sát lớn và hình thức tồi tệ cho SE, nhưng tôi không thể hoàn thành công việc ngay bây giờ. Tìm kiếm riêng của tôi cho câu trả lời cho câu hỏi này dường như chỉ ra rằng hàm gDistance từ các rgeos của thư viện sẽ thực hiện những gì OP dự định: tìm khoảng cách ngắn nhất giữa các cạnh. Nếu, trong sự vội vàng của tôi để đáp ứng một thời hạn chặt chẽ, tôi đã giải thích sai về OP hoặc Jeffrey Evans lời xin lỗi chân thành của tôi.
csfowler
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.