我试图缓冲半径为100公里的数据集中的点。我使用了包gBuffer
中的rgeos
函数。这就是我到目前为止所拥有的:
head( sampledf )
# postalcode lat lon city province
#1 A0A0A0 47.05564 -53.20198 Gander NL
#4 A0A1C0 47.31741 -52.81218 St. John's NL
coordinates( sampledf ) <- c( "lon", "lat" )
proj4string( sampledf ) <- CRS( "+proj=longlat +datum=WGS84" )
distInMeters <- 1000
pc100km <- gBuffer( sampledf, width=100*distInMeters, byid=TRUE )
我收到以下警告:
在gBuffer中(sampledf,width = 100 * distInMeters,byid = TRUE): 不预测空间对象; GEOS期望平面坐标
根据我的理解/阅读,我需要更改坐标参照系(CRS), 尤其是来自“地理”数据集的投影。预计&#39; 我不确定如何改变这一点。这些都是加拿大的地址,我可以补充一下。 所以NAD83在我看来是一个自然的选择,但我可能错了。
非常感谢任何/所有帮助。
答案 0 :(得分:17)
随着更多的挖掘,事实证明使用“预测”&#39;坐标参考系统就像
一样简单# To get Statscan CRS, see here:
# http://spatialreference.org/ref/epsg/3347/
pc <- spTransform( sampledf, CRS( "+init=epsg:3347" ) )
EPSSC3347,由STATSCAN使用(适用于加拿大地址),使用lambert conformal conic投影。请注意,NAD83是不合适的:它是一个地理位置,而不是“预测”的地理位置&#39; CRS。缓冲点
pc100km <- gBuffer( pc, width=100*distm, byid=TRUE )
# Add data, and write to shapefile
pc100km <- SpatialPolygonsDataFrame( pc100km, data=pc100km@data )
writeOGR( pc100km, "pc100km", "pc100km", driver="ESRI Shapefile" )
答案 1 :(得分:2)
正如@MichaelChirico所指出的那样,投影数据以供使用rgeos::gBuffer()
时应格外小心。我不是大地测量学专家,但是据我从ESRI这篇文章(Understanding Geodesic Buffering)所了解的,投射然后应用gBuffer
意味着实际上产生了 Euclidean 缓冲区,而不是< strong> Geodesic 。欧式缓冲区受投影坐标系引入的变形的影响。如果您的分析涉及较大的缓冲区,尤其是在较大区域的纬度范围较大(我认为加拿大是一个不错的候选人),那么这些失真可能会令人担心。
前段时间,我遇到了同一问题,我的问题针对gis.stackexchange-Euclidean and Geodesic Buffering in R。我认为我当时提出的R代码以及给出的答案也与此问题相关。
主要思想是利用geosphere::destPoint()
。有关更多详细信息和更快的替代方法,请参见上面提到的gis.stackexchange链接。这是我对您的两点进行的较早尝试:
library(geosphere)
library(sp)
pts <- data.frame(lon = c(-53.20198, -52.81218),
lat = c(47.05564, 47.31741))
pts
#> lon lat
#> 1 -53.20198 47.05564
#> 2 -52.81218 47.31741
make_GeodesicBuffer <- function(pts, width) {
# A) Construct buffers as points at given distance and bearing ---------------
dg <- seq(from = 0, to = 360, by = 5)
# Construct equidistant points defining circle shapes (the "buffer points")
buff.XY <- geosphere::destPoint(p = pts,
b = rep(dg, each = length(pts)),
d = width)
# B) Make SpatialPolygons -------------------------------------------------
# Group (split) "buffer points" by id
buff.XY <- as.data.frame(buff.XY)
id <- rep(1:dim(pts)[1], times = length(dg))
lst <- split(buff.XY, id)
# Make SpatialPolygons out of the list of coordinates
poly <- lapply(lst, sp::Polygon, hole = FALSE)
polys <- lapply(list(poly), sp::Polygons, ID = NA)
spolys <- sp::SpatialPolygons(Srl = polys,
proj4string = CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))
# Disaggregate (split in unique polygons)
spolys <- sp::disaggregate(spolys)
return(spolys)
}
pts_buf_100km <- make_GeodesicBuffer(as.matrix(pts), width = 100*10^3)
# Make a kml file and check the results on Google Earth
library(plotKML)
#> plotKML version 0.5-9 (2019-01-04)
#> URL: http://plotkml.r-forge.r-project.org/
kml(pts_buf_100km, file.name = "pts_buf_100km.kml")
#> KML file opened for writing...
#> Writing to KML...
#> Closing pts_buf_100km.kml
由reprex package(v0.2.1)于2019-02-11创建
为了开玩笑,我将函数包装在一个包装中-geobuffer
这里是一个例子:
# install.packages("devtools") # if you do not have devtools, then install it
devtools::install_github("valentinitnelav/geobuffer")
library(geobuffer)
pts <- data.frame(lon = c(-53.20198, -52.81218),
lat = c(47.05564, 47.31741))
pts_buf_100km <- geobuffer_pts(xy = pts, dist_m = 100*10^3)
由reprex package(v0.2.1)于2019-02-11创建
其他人可能会提出更好的解决方案,但是目前,这对我的问题很有效,希望也可以解决其他人的问题。