合并 SpatialPolygonsDataframe 的多边形
merging polygons of a SpatialPolygonDataframe
我创建了一个 SpatialPolygonsDataFrame,其中国家与地区相关联。这是它的样子 https://cloudstor.aarnet.edu.au/plus/index.php/s/RpYr3xyMrmhaGKA(EDU link 有数据):
由于对象太大而无法处理,而且我只对信息区域而不是国家感兴趣,因此我希望合并每个区域内的国家。换句话说,我希望为每个区域创建一个多边形。
我已尝试 运行 以下命令,但 运行 需要几个小时,而且我一直无法查看它们是否正常工作。
library(rgdal)
regions = readOGR("./regionscountriesSTACK.shp")
library(maptools)
regions <- unionSpatialPolygons(regions, IDs=regions@data$REGION)
library(rgeos)
gUnionCascaded(regions, id = regions@data$REGION)
gUnaryUnion(regions, id = regions@data$REGION)
有什么有效的处理方法建议吗?非常感谢!
您需要:
1)简化多边形,它们可能太复杂而无法开始,特别是如果你想按区域聚合它们。使用 rgeos 包中的 gSimplify
。没有数据很难进一步帮助你。
2) 去除空洞,它们占用了很多 space 并且在简化时会导致麻烦
3) 进行联合和简化,允许对数据进行严格的简化
以下代码结合了所有这些,逐个国家执行也可以看到事情的进展:
library(rgdal)
library(maptools)
library(rgeos)
# Remove all holes that are bigger than "limitholes", by default all of them
RemoveHoles <- function(SPol,limitHoles=+Inf){
fn <- function(subPol){
if(subPol@hole && subPol@area < limitHoles)
keep <- FALSE
else
keep <- TRUE
return(keep)
}
nPol <- length(SPol)
newPols <- list()
for(iPol in 1:nPol){
subPolygons <- list()
pol <- SPol@polygons[[iPol]]
for(iSubPol in 1:length(pol@Polygons)){
subPol <- pol@Polygons[[iSubPol]]
if(fn(subPol))
subPolygons[[length(subPolygons)+1]] <- subPol
}
newPols[[length(newPols)+1]] <- Polygons(subPolygons,pol@ID)
}
newSPol <- SpatialPolygons(newPols,proj4string=CRS(proj4string(SPol)))
# SPolSimple <- gSimplify(newSPol,tol=0.01)
newSPol <- createSPComment(newSPol)
return(newSPol)
}
# Union Polygon (country) by polygon for a given region
UnionSimplifyPolByPol <- function(subReg,precision=0.2){
# if(length(subReg)>1){
# out <- unionSpatialPolygons(subReg[1:2,],rep(1,2),threshold=0.1)
# out <- RemoveHoles(out)
# }
out <- c()
for(iCountry in 1:length(subReg)){
cat("Adding:",subReg@data[iCountry,"COUNTRY"],"\n")
toAdd <- gSimplify(as(subReg[iCountry,],"SpatialPolygons"),
tol=precision,topologyPreserve=TRUE)
toAdd <- RemoveHoles(toAdd)
if(is.null(out)){
out <- toAdd
}else{
toUnite <- rbind(out,toAdd)
out <- unionSpatialPolygons(toUnite,
IDs=rep(1,2),
threshold=precision)
}
out <- RemoveHoles(out)
# plot(out)
}
return(out)
}
# import the data
countries <- readOGR("regionscountriesSTACK.shp")
# you don't want to be bothered by factors
countries@data$COUNTRY <- as.character(countries@data$COUNTRY)
countries@data$REGION <- as.character(countries@data$REGION)
# aggregate region by region
vectRegions <- unique(countries@data$REGION)
world <- c()
for(iRegion in 1:length(vectRegions)){
regionName <- vectRegions[iRegion]
cat("Region:",regionName)
region <- UnionSimplifyPolByPol(countries[which(countries$REGION==regionName),])
region <- spChFIDs(region,regionName)
if(is.null(world)){
world <- region
}else{
world <- rbind(world,region)
}
plot(world)
}
此解决方案在包 spatDataManagement 中实现。如果您只对地区感兴趣,您可能还想使用 rworldmap
来制作更轻便的世界地图。然后它变成:
library("spatDataManagement")
library("rworldmap")
levels(countriesLow@data$REGION)<-c(levels(countriesLow@data$REGION),"Other")
countriesLow@data$REGION[which(is.na(countriesLow@data$REGION))] <- "Other"
vectRegions <- unique(countriesLow@data$REGION)
world <- c()
for(iRegion in 1:length(vectRegions)){
regionName <- vectRegions[iRegion]
cat("Region:",regionName)
region <- UnionSimplifyPolByPol(countriesLow[which(countriesLow$REGION==regionName),])
region <- spChFIDs(region,gsub(" ","",regionName)) # IDs can't have spaces
if(is.null(world)){
world <- region
}else{
world <- rbind(world,region)
}
}
world <- SpatialPolygonsDataFrame(world,data.frame(id=1:length(world),name=vectRegions),match.ID=FALSE)
plot(world,col=world$id)
这张新地图要小得多(2.8 兆字节)。
我创建了一个 SpatialPolygonsDataFrame,其中国家与地区相关联。这是它的样子 https://cloudstor.aarnet.edu.au/plus/index.php/s/RpYr3xyMrmhaGKA(EDU link 有数据):
由于对象太大而无法处理,而且我只对信息区域而不是国家感兴趣,因此我希望合并每个区域内的国家。换句话说,我希望为每个区域创建一个多边形。 我已尝试 运行 以下命令,但 运行 需要几个小时,而且我一直无法查看它们是否正常工作。
library(rgdal)
regions = readOGR("./regionscountriesSTACK.shp")
library(maptools)
regions <- unionSpatialPolygons(regions, IDs=regions@data$REGION)
library(rgeos)
gUnionCascaded(regions, id = regions@data$REGION)
gUnaryUnion(regions, id = regions@data$REGION)
有什么有效的处理方法建议吗?非常感谢!
您需要:
1)简化多边形,它们可能太复杂而无法开始,特别是如果你想按区域聚合它们。使用 rgeos 包中的 gSimplify
。没有数据很难进一步帮助你。
2) 去除空洞,它们占用了很多 space 并且在简化时会导致麻烦
3) 进行联合和简化,允许对数据进行严格的简化
以下代码结合了所有这些,逐个国家执行也可以看到事情的进展:
library(rgdal)
library(maptools)
library(rgeos)
# Remove all holes that are bigger than "limitholes", by default all of them
RemoveHoles <- function(SPol,limitHoles=+Inf){
fn <- function(subPol){
if(subPol@hole && subPol@area < limitHoles)
keep <- FALSE
else
keep <- TRUE
return(keep)
}
nPol <- length(SPol)
newPols <- list()
for(iPol in 1:nPol){
subPolygons <- list()
pol <- SPol@polygons[[iPol]]
for(iSubPol in 1:length(pol@Polygons)){
subPol <- pol@Polygons[[iSubPol]]
if(fn(subPol))
subPolygons[[length(subPolygons)+1]] <- subPol
}
newPols[[length(newPols)+1]] <- Polygons(subPolygons,pol@ID)
}
newSPol <- SpatialPolygons(newPols,proj4string=CRS(proj4string(SPol)))
# SPolSimple <- gSimplify(newSPol,tol=0.01)
newSPol <- createSPComment(newSPol)
return(newSPol)
}
# Union Polygon (country) by polygon for a given region
UnionSimplifyPolByPol <- function(subReg,precision=0.2){
# if(length(subReg)>1){
# out <- unionSpatialPolygons(subReg[1:2,],rep(1,2),threshold=0.1)
# out <- RemoveHoles(out)
# }
out <- c()
for(iCountry in 1:length(subReg)){
cat("Adding:",subReg@data[iCountry,"COUNTRY"],"\n")
toAdd <- gSimplify(as(subReg[iCountry,],"SpatialPolygons"),
tol=precision,topologyPreserve=TRUE)
toAdd <- RemoveHoles(toAdd)
if(is.null(out)){
out <- toAdd
}else{
toUnite <- rbind(out,toAdd)
out <- unionSpatialPolygons(toUnite,
IDs=rep(1,2),
threshold=precision)
}
out <- RemoveHoles(out)
# plot(out)
}
return(out)
}
# import the data
countries <- readOGR("regionscountriesSTACK.shp")
# you don't want to be bothered by factors
countries@data$COUNTRY <- as.character(countries@data$COUNTRY)
countries@data$REGION <- as.character(countries@data$REGION)
# aggregate region by region
vectRegions <- unique(countries@data$REGION)
world <- c()
for(iRegion in 1:length(vectRegions)){
regionName <- vectRegions[iRegion]
cat("Region:",regionName)
region <- UnionSimplifyPolByPol(countries[which(countries$REGION==regionName),])
region <- spChFIDs(region,regionName)
if(is.null(world)){
world <- region
}else{
world <- rbind(world,region)
}
plot(world)
}
此解决方案在包 spatDataManagement 中实现。如果您只对地区感兴趣,您可能还想使用 rworldmap
来制作更轻便的世界地图。然后它变成:
library("spatDataManagement")
library("rworldmap")
levels(countriesLow@data$REGION)<-c(levels(countriesLow@data$REGION),"Other")
countriesLow@data$REGION[which(is.na(countriesLow@data$REGION))] <- "Other"
vectRegions <- unique(countriesLow@data$REGION)
world <- c()
for(iRegion in 1:length(vectRegions)){
regionName <- vectRegions[iRegion]
cat("Region:",regionName)
region <- UnionSimplifyPolByPol(countriesLow[which(countriesLow$REGION==regionName),])
region <- spChFIDs(region,gsub(" ","",regionName)) # IDs can't have spaces
if(is.null(world)){
world <- region
}else{
world <- rbind(world,region)
}
}
world <- SpatialPolygonsDataFrame(world,data.frame(id=1:length(world),name=vectRegions),match.ID=FALSE)
plot(world,col=world$id)
这张新地图要小得多(2.8 兆字节)。