R에서 다각형 사이의 {최소} 거리 계산


9

종 분포 (표면 파일에서 다각형 병합)의 표면적을 계산했지만이 영역은 꽤 멀리 떨어진 다각형으로 구성 될 수 있기 때문에 분산 정도를 계산하고 싶습니다. 내가 지금까지 한 것은 아래의 더미 예제에서와 같이 각 다각형의 중심을 검색하고 이들 사이의 거리를 계산 한 다음 이들을 사용하여 변동 계수를 계산하는 것입니다.

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

세 개의 다각형과 그 중심의 플롯

여기에 이미지 설명을 입력하십시오

꽤 많은 경우에, 위의 예에서 파란색과 같은 일부 다각형이 나머지에 비해 상당히 커서 거리가 더 멀어 지므로이 방법이 매우 유용한 지 확실하지 않습니다. 예를 들어 호주의 중심은 서부 국경과 파파 우의 거리가 거의 같습니다.

내가 얻고 싶은 것은 대체 접근법에 대한 정보입니다. 예를 들어 다각형 간의 거리를 어떻게 또는 어떤 함수로 계산할 수 있습니까?

위의 SpatialPolygon 데이터 프레임을 PointPatterns (ppp)로 변환하여 모든 점 사이의 거리를 계산할 {spatstat}수 있도록 테스트했습니다 nndist() {spatstat}. 그러나 꽤 넓은 영역 (다수의 다각형과 큰 영역)을 다루기 때문에 행렬이 커지고 다각형 사이의 최소 거리 에 계속 도달하는 방법을 모르겠습니다 .

나는 또한 그 기능을 살펴 gDistance {rgeos}봤지만, 그것은 내 영역이 여러 곳을 넘어갈 수 있기 때문에 문제가 될 수있는 투영 된 데이터에서만 작동한다고 생각한다 EPSG areas. 함수에 대해서도 동일한 문제가 발생합니다 crossdist {spatstat}.


1
postgres/postgis이외에도 사용을 고려 하시겠습니까 R? 나는 대부분의 작업을 수행하는 워크 플로를 사용 R했지만 데이터를 사용하여 액세스하는 데이터베이스에 데이터를 저장합니다 sqldf. 이를 통해 모든 postgis기능 을 사용할 수 있습니다 (다각형 사이의 거리가 직선 임)
djq

@ djq : 댓글 주셔서 감사합니다. 그래, 나는 분명히 그것을 갈 것이다 :) 나는 데이터베이스를 구축하기 시작 postgres했지만 데이터베이스와 R...
jO

답변:


9

이 분석은 "spdep"패키지에서 수행 할 수 있습니다. 관련 인접 함수에서 "longlat = TRUE"를 사용하면이 함수는 큰 원 거리를 계산하고 거리 단위로 킬로미터를 반환합니다. 아래 예제에서는 결과 거리 목록 객체 ( "dist.list")를 행렬 또는 data.frame으로 강제 변환 할 수 있지만 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) } ) )

의견을 말하고 spdeb패키지에 대한 통찰력을 가져 주셔서 감사 합니다. 명확히하기 위해이 접근법은 내 예와 동일한 결과를 산출합니다.
jO.

위의 의견이 보이지 않는 경우를 대비하여
jO.

응답이 중심 사이의 거리를 계산하는 데 유용한 코드를 제공하지만 다각형 경계의 가장 가까운 두 지점 사이의 거리를 찾는 방법 인 OP의 중심점을 다루지 않습니다.
csfowler

SE에 대한 거대한 경찰 아웃과 나쁜 형태이지만 지금은 전체 작업을 수행 할 수 없습니다. 이 질문에 대한 답을 직접 찾은 것은 라이브러리 rgeos의 gDistance 함수가 OP가 의도 한 것을 수행 할 것임을 나타냅니다. 가장자리 사이의 가장 짧은 거리를 찾으십시오. 촉박 한 마감일을 지키기 위해 서둘러 OP 또는 Jeffrey Evans를 진심으로 사과했다면 진심으로 사과드립니다.
csfowler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.