使用R交叉点使用两个shapefile图层创建多边形内部多边形键

时间:2017-12-01 19:46:08

标签: r gis intersection shapefile rgdal

数据

我有两个形状文件标记了巴基斯坦nationalprovincial选举选区的界限。

目标

我正在尝试使用R来创建一个密钥,该密钥将根据这些数据中的坐标生成一个列表,其中包含哪些省级选区“包含在内”或与哪些国家级选区交叉。例如,NA-01对应于PA-01,PA-02,PA-03; NA-02对应于PA-04和PA-05等(关键将最终用于链接包含国家和省级选举结果的单独数据帧;我已经找到了这一部分。)

我只有通过反复试验获得的基本/中级R技能,没有使用R以外的GIS数据的经验。

尝试的解决方案

我能找到的最接近这个问题的解决方案是this guide来计算R中的交叉区域。但是,我无法成功复制三种提议方法中的任何一种(提问者使用一般的TRUE) / FALSE报告交叉点,或更精确的重叠区域计算)。

代码

# import map files

NA_map <- readOGR(dsn = "./National_Constituency_Boundary", layer = "National_Constituency_Boundary")
PA_map <- readOGR(dsn = "./Provincial_Constituency_Boundary", layer = "Provincial_Constituency_Boundary")

# Both are now SpatialPolygonsDataFrame objects of 273 and 577 elements, respectively.
# If relevant, I used spdpylr to tweak some of data attribute names (for use later when joining to electoral dataframes):

NA_map <- NA_map %>% 
rename(constituency_number = NA_Cons,
     district_name = District,
     province = Province)

PA_map <- PA_map %>%
rename(province = PROVINCE,
     district_name = DISTRICT,
     constituency_number = PA)

# calculate intersections, take one

Results <- gIntersects(NA_map, PA_map, byid = TRUE)
# this creates a large matrix of 157,521 elements

rownames(Results) <- NA_map@data$constituency_number
colnames(Results) <- PA_map@data$constituency_number

但是,尝试添加rowname / colname标签会给出错误消息:

Error in dimnames(x) <- dn : 
  length of 'dimnames' [1] not equal to array extent

如果没有rowname / colname标签,我无法读取叠加矩阵,也不能确定如何过滤它们,以便生成一个只有TRUE交叉点的列表,这些交叉点有助于制作NA-PA密钥。

我还尝试复制另外两个提出的解决方案来计算确切的重叠区域:

# calculate intersections, take two

pi <- intersect(NA_map, PA_map)
# this generates a SpatialPolygons object with 273 elements

areas <- data.frame(area=sapply(pi@polygons, FUN = function(x) {slot(x, 'area')}))
# this calculates the area of intersection but has no other variables
row.names(areas) <- sapply(pi@polygons, FUN=function(x) {slot(x, 'ID')})

这会生成错误消息:

Error in `row.names<-.data.frame`(`*tmp*`, value = c("2", "1", "4", "5",  : 
  duplicate 'row.names' are not allowed
In addition: Warning message:
non-unique value when setting 'row.names': ‘1’ 

因此,当我尝试使用

将区域附加到属性信息时
attArrea <- spCbind(pi, areas)

我收到错误消息

Error in spCbind(pi, areas) : row names not identical

尝试第三种方法:

# calculate intersections, take three
pi <- st_intersection(NA_map, PA_map)

生成错误消息:

Error in UseMethod("st_intersection") : 
  no applicable method for 'st_intersection' applied to an object of class "c('SpatialPolygonsDataFrame', 'SpatialPolygons', 'Spatial', 'SpatialPolygonsNULL', 'SpatialVector')"

我知道我的SPDF地图不能用于第三种方法,但是从描述中不清楚转换它并尝试这种方法需要哪些步骤。

求助的请求

任何有关使用这些方法所需的修正的建议,或指向其他一些方法的指示,都将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:1)

以下是一些示例数据

library(raster)
p <- shapefile(system.file("external/lux.shp", package="raster"))
p1 <- aggregate(p, by="NAME_1")
p2 <- p[, 'NAME_2']

所以我们有p1表示区域,而p2表示低级别。

现在我们可以做到

x <- intersect(p1, p2)
# or  x <- union(p1, p2)
data.frame(x)

哪个应该(并且是)与原始

相同
data.frame(p)[, c('NAME_1', 'NAME_2')]

要获取多边形的区域,可以执行

 x$area <- area(x) / 1000000  # divide to get km2

由于边界略有变化,可能会有许多“条子”,非常小的多边形。这对你来说可能无关紧要。

但另一种方法可能是通过质心匹配:

y <- p2
e <- extract(p1, coordinates(p2))
y$NAME_1 <- e$NAME_1
data.frame(y)

答案 1 :(得分:0)

您的代码不是自包含的,因此我没有尝试复制您报告的错误。

但是,使用sf软件包(用于在不久的将来取代rgeosrgdalsp非常简单,获取所需的“密钥” )。见这里:

library(sf)

# Download shapefiles
national.url <- 'https://data.humdata.org/dataset/5d48a142-1f92-4a65-8ee5-5d22eb85f60f/resource/d85318cb-dcc0-4a59-a0c7-cf0b7123a5fd/download/national-constituency-boundary.zip'
provincial.url <- 'https://data.humdata.org/dataset/137532ad-f4a9-471e-8b5f-d1323df42991/resource/c84c93d7-7730-4b97-8382-4a783932d126/download/provincial-constituency-boundary.zip'
download.file(national.url, destfile = file.path(tempdir(), 'national.zip'))
download.file(provincial.url, destfile = file.path(tempdir(), 'provincial.zip'))

# Unzip shapefiles
unzip(file.path(tempdir(), 'national.zip'), exdir = file.path(tempdir(), 'national'))
unzip(file.path(tempdir(), 'provincial.zip'), exdir = file.path(tempdir(), 'provincial'))

# Read map files
NA_map <- st_read(dsn = file.path(tempdir(), 'national'), layer = "National_Constituency_Boundary")
PA_map <- st_read(dsn = file.path(tempdir(), 'provincial'), layer = "Provincial_Constituency_Boundary")

# Get sparse list representation of intersections
intrs.sgpb <- st_intersects(NA_map, PA_map) 
length(intrs.sgpb) # One list element per national constituency
# [1] 273
print(intrs.sgpb[[1]]) # Indices of provnicial constituencies intersecting with first national constituency
# [1] 506 522 554 555 556
print(PA_map$PROVINCE[intrs.sgpb[[1]]])[1] # Name of first province intersecting with first national constituency
# [1] KHYBER PAKHTUNKHWA