简体   繁体   中英

Converting a Spatial Polygon to map objects

I am attempting to convert a spatial polygon object in R to a map object. I have managed to do so using previously answered questions, most specifically ( In R, how can I convert SpatialPolygons* to map objects ), but I am having the same problem as the person in this thread: I get strange polygon linkings that render the map unusable.

I have included the complete code below for replication.

Thank you for any assistance.

library(sp)
library(spdep)
library(maps)
library(rgdal)

## load a file from GADM (you just have to specify the countries "special part" of the file name, like "ARG" for Argentina. Optionally you can specify which level you want to have
loadGADM <- function (fileName, level = 0, ...) {
load(url(paste("http://gadm.org/data/rda/", fileName, "_adm", level, ".RData", sep     = "")))
gadm
}

## the maps objects get a prefix (like "ARG_" for Argentina)
changeGADMPrefix <- function (GADM, prefix) {
GADM <- spChFIDs(GADM, paste(prefix, row.names(GADM), sep = "_"))
GADM
}

## load file and change prefix
loadChangePrefix <- function (fileName, level = 0, ...) {
theFile <- loadGADM(fileName, level)
theFile <- changeGADMPrefix(theFile, fileName)
theFile
}

## this function creates a SpatialPolygonsDataFrame that contains all maps you specify in "fileNames".
## E.g.: 
## spdf <- getCountries(c("ARG","BOL","CHL"))
## plot(spdf) # should draw a map with Brasil, Argentina and Chile on it.
getCountries <- function (fileNames, level = 0, ...) {
polygon <- sapply(fileNames, loadChangePrefix, level)
polyMap <- do.call("rbind", polygon)
polyMap
}



indiamap <- getCountries("IND",level=1)

xx <- indiamap
require(reshape)
xx@data$id <- rownames(xx@data)

# Convert to dataframe
xx.df <- as.data.frame(xx)

#Fortfy automagic
require(ggplot2)
xx.fort <- fortify(xx, region="id")

# Join operation - one row per coordinate vector
require(plyr)
xx <- join(xx.fort, xx.df,by="id")

# Split by ID because we need to add NA at end of each set of polygon coordinates to 'break' the line
xxSp <- split(xx, xx$id)

# Need to insert NA at end of each polygon shape to cut off that shape
xxL <- do.call( rbind , (lapply( xxSp , function(x) { j <- x[ nrow(x) , ] ; j[1:2] <- c(NA,NA); rbind( x , j ) })) )


# Create list object with same structure as map object
xxMap <- list( x = xxL$long , y = xxL$lat , range = c( range(xxL$long) , range(xxL$lat) ) , names = as.character(unique( xxL$NAME ) ) )

# Define as a map class object
attr(xxMap , "class") <- "map"

# Plot!!
map( xxMap )

The problem is that each some id s (provinces) consist of several polygons, eg the islands. The SpatialPolygonsDataFrame has information to tell that these separate polygons are the same id but should not be connected by lines. By converting to map , that information is lost. In your workaround, you're only adding NA s between id s, not between all separate polygons.

The trick is to generate a unique id for all separate piece, so a NA can be added after each little piece. The xx created by join contains a field called piece . It seems this field has a separate number for each polygon within a single id . So, for instance polygon with id == 4 consists of 3 pieces, eg 3 islands. A unique id for all polygons can then be generated by:

xx$myid <- xx$ID_1*1000 + as.numeric(xx$piece)

It takes the ID of each province * 1000 plus the id of each piece. The maximum of pieces within a polygon for India is 212. The complete code is then:

indiamap <- getCountries("IND",level=1)

xx <- indiamap
require(reshape)
xx@data$id <- rownames(xx@data)

# Convert to dataframe
xx.df <- as.data.frame(xx)
# xx.df$myid = xx$ID1*100 + xx$piece

#Fortfy automagic
require(ggplot2)
xx.fort <- fortify(xx, region="id")

# Join operation - one row per coordinate vector
require(plyr)
xx <- join(xx.fort, xx.df,by="id")
unique(xx$piece)

# generate unique id for each polygon piece
xx$myid <- xx$ID_1*1000 + as.numeric(xx$piece)

# Split by myid because we need to add NA at end of each set of polygon coordinates to 'break' the line
xxSp <- split(xx, xx$myid)

# Need to insert NA at end of each polygon shape to cut off that shape
# xxL <- do.call( rbind , (lapply( xxSp , function(x) { j <- x[ nrow(x) , ] ; j[1:2] <- c(NA,NA); rbind( x , j ) })) )
xxL <- do.call( rbind , (lapply( xxSp , function(x) { j <- x[nrow(x) , ] ; j[1:2] <- c(NA,NA); rbind( x , j ) })) )


# Create list object with same structure as map object
xxMap <- list( x = xxL$long , y = xxL$lat , range = c( range(xxL$long) , range(xxL$lat) ) , names = as.character(unique( xxL$NAME_1 ) ) )

# Define as a map class object
attr(xxMap , "class") <- "map"

map( xxMap , fill=T, col=2)

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM