21

I have created 2 polygons in QGIS. Using them in R, polygons become automatically SpatialPolygonsDataFrame (SPDF). I would like to merge them into single SPDF (as is super easy in ArcGis using Tool Merge). I am sure that there should be simple way how to complete that in R, but I can't find how. the merge function seems to merge only data.frames, aggregate function dissolve multiple polygons into one shp, gIntersect (by typing join function) returns logical value, not at all the SPDF.

enter image description here

data are available here: http://ulozto.cz/xpoo5jfL/ab-zip

library(sp)
library(raster)
library(rgeos)
library(spatstat)
library(rgdal)     
library(maptools)

setwd("C:/...")
a<-readOGR(dsn=getwd(), layer="pol.a")
b<- readOGR(dsn=getwd(), layer="pol.b")

ab<-merge(a, b)  # what tool if not "merge" to use??
19

If you do not need to merge topology, but just add new polygons, you can simply use:

ab <- rbind(a,b)

If you get a "non-unique Polygons ID slot values" error it means that the rownames of the objects are the same. To fix this you can use spChFIDs to change the rownames and associated slot relationships. Since the slots in the object use the rownames to associate the object, you cannot just change row.names in the @data slot.

b <- spChFIDs(b, paste("b", row.names(b), sep="."))

The union (union_sp) function in the raster package is doing this, and calling gIntersects from rgeos, behind the scenes and is a very convenient helper function.

****Edit 08-06-2018 There is an undocumented argument that can be used to skip the duplicate ID issue.

ab <- rbind(a, b, makeUniqueIDs = TRUE) 
  • Hi, thank you, I tried this one but got an error: Error in validObject(res) : invalid class “SpatialPolygons” object: non-unique Polygons ID slot values. How can I deal with this error? – maycca Jul 22 '15 at 17:00
  • 3
    You can do: ab <- bind(a, b) to avoid that error – Robert Hijmans Dec 6 '17 at 7:05
  • raster::union does not currently work with spatialPOINTSdataframes – Mox Mar 13 '18 at 23:08
19

Super easy solution provided by @mdsumner:

library(sp)
library(raster)
library(rgeos)
library(spatstat)
library(rgdal)     
library(maptools)

setwd("C:/...")
a<-readOGR(dsn=getwd(), layer="pol.a")
b<- readOGR(dsn=getwd(), layer="pol.b")

# use union in {raster} package ?raster::union
ab<-union(a, b)

resulted in :

class(ab)

[1] "SpatialPolygonsDataFrame"
attr(,"package")
[1] "sp"

enter image description here

  • 6
    Super easy solution provided by Robert Hijmans, the author of raster :) – mdsumner Jul 22 '15 at 22:18
  • 'Union' does not (currently) work for spatialpointsdataframes, although I am told it will in the next release. @RobertH has suggested the use of rbind, although I'm not exactly clear on how that works. – Mox Mar 13 '18 at 23:01
  • Details here: gis.stackexchange.com/questions/274609/… – Mox Mar 13 '18 at 23:01
  • It looks like raster::union works for the SpatialLinesDataFrame class as well! – spacedSparking Nov 26 '18 at 23:43
1
library(sp)
data(meuse)
plot(meuse)
slotNames(meuse) #".Data"     "names"     "row.names" ".S3Class" 
coordinates(meuse) <- ~x+y #Add "ID" column to "meuse"
slotNames(meuse) #[1] "data"        "coords.nrs"  "coords"      "bbox"        "proj4string"
class(meuse) #[1] "SpatialPointsDataFrame"
names(meuse@data)
#[1] "cadmium" "copper"  "lead"    "zinc"    "elev"    "dist"    "om"      "ffreq"   "soil"    "lime"   
#[11] "landuse" "dist.m"
meuse@data <- data.frame(ID=1:nrow(meuse), meuse@data) #adds an ID field
names(meuse@data)
#[1] "ID"      "cadmium" "copper"  "lead"    "zinc"    "elev"    "dist"    "om"      "ffreq"   "soil"   
#[11] "lime"    "landuse" "dist.m" 
#Create a data.frame "df.new" with "IDS" (note different name) and "y" columns.
meuse_table.df <- data.frame(IDS=1:nrow(meuse), y=runif(nrow(meuse)))
class(meuse_table.df) #"data.frame"
#Now we can merge "df.new" to "meuse" (@data slot)
meuse <- merge(meuse, meuse_table.df, by.x = "ID", by.y = "IDS")
#create a new file named meuse, consisting of a merge of:
#   the meuse spatial points (from the original)
#   the dataframe created from the original, using the data.frame command
#   BY the field "ID" in the spatialpointsdataframe
#   By the field "IDS" in the tabular dataframe (df.new) 
head(meuse@data)
# I think the source of unease is that adding an ID field to both files 
#is based on them having the same number of rows in the same order. 
#in ArcGIS, this would be an unreasonable and dangerous assumption.
#R seems to have some sort of 'innate' key field, based on the order read it. 
#This is all great when splitting one file, and merging it back together.
#but what about two files? 
#I think it can be done, but it's a three-step process. 
#First, merge the polygons. Add an ID field, as above.
#Second, merge the tables (as dataframes), and add ID's. as above. 
#Third, attach the merged tables to the merged polygons. 
#For it to work, the order of things in the merge (polgyons, dataframe) needs be identfical. 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.