I have a SpatialPointsDataFrame in R that looks like this:
coordinates id order hole piece group box_id
326 (-94.4, 27.6586) 47 1 FALSE 1 47.1 1
327 (-93.64, 27.6232) 47 2 FALSE 1 47.1 1
328 (-92.04, 27.7649) 47 3 FALSE 1 47.1 1
329 (-90.36, 27.0903) 47 4 FALSE 1 47.1 1
330 (-91.12, 25.6929) 47 5 FALSE 1 47.1 1
331 (-92.92, 25.6569) 47 6 FALSE 1 47.1 1
332 (-93.44, 26.0169) 47 7 FALSE 1 47.1 1
333 (-94.4, 25.9809) 47 8 FALSE 1 47.1 1
334 (-94.4, 27.6586) 47 9 FALSE 1 47.1 1
335 (-92.04, 27.7649) 48 1 FALSE 1 48.1 2
336 (-93.64, 27.6232) 48 2 FALSE 1 48.1 2
337 (-94.4, 27.6586) 48 3 FALSE 1 48.1 2
338 (-94.4, 27.8356) 48 4 FALSE 1 48.1 2
339 (-93.64, 27.7649) 48 5 FALSE 1 48.1 2
340 (-90.28, 28.1182) 48 6 FALSE 1 48.1 2
341 (-90.56, 27.9417) 48 7 FALSE 1 48.1 2
342 (-92.04, 27.7649) 48 8 FALSE 1 48.1 2
100 (-94.4, 27.8356) 20 1 FALSE 1 20.1 3
101 (-94.4, 28.0829) 20 2 FALSE 1 20.1 3
102 (-90.28, 28.1182) 20 3 FALSE 1 20.1 3
103 (-93.64, 27.7649) 20 4 FALSE 1 20.1 3
104 (-94.4, 27.8356) 20 5 FALSE 1 20.1 3
(row names/numbers are not in order because I sorted by box_id column)
These points are nodes of polygons (identified by box_id). I want to write this as a polygon shape file to read into GIS programs, but I'm having trouble converting it into a SpatialPolygonDataFrame (to then use writeOGR) or to directly write it to a shp file. Any help would be appreciate. I'm new to GIS with R, so apologies if I'm missing something obvious.
So here's another solution, conceptually similar to @JoshO'Brien's. This one accommodates sub-polygons (multiple groups for a given id) and creates an object of class SpatialPolygonsDataFrame, with included data section (e.g., the attributes table). This is fully exportable to an ESRI shapefile.
First, as an example, we create a SpatialPointsDataFrame with the same format as yours. The id
column identifies Polygon ID
and the group
column identifies sub-polygons for a given polygon. In this example we have 3 polygons, two of which have 1 sub-Polygon, and the third which has 3 sub-Polygons. We also create a data frame data
(the attributes table) which in this case associates polygon ID with box_id.
# this code just creates a sample SpatialPointsDataFrame
x <- c(-10,-10,10,10,-10)
y <- c(-10,10,10,-10,-10)
df.1 <- data.frame(x,y,id=47, order=1:5,hole=F,piece=1,group=47.1,box_id=1)
coordinates(df.1)=c("x","y")
x <- c(+15+3*cos(2*pi/5*(0:5)))
y <- c(-15+3*sin(2*pi/5*(0:5)))
df.2 <- data.frame(x,y,id=48, order=1:6,hole=F,piece=1,group=48.1,box_id=2)
coordinates(df.2)=c("x","y")
x <- c(-15+2*cos(2*pi/8*(0:8)))
y <- c(+15+2*sin(2*pi/8*(0:8)))
df.3.1 <- data.frame(x,y,id=20, order=1:9,hole=F,piece=1,group=20.1,box_id=3)
coordinates(df.3.1)=c("x","y")
x <- c(0+2*cos(2*pi/8*(0:8)))
y <- c(+15+2*sin(2*pi/8*(0:8)))
df.3.2 <- data.frame(x,y,id=20, order=1:9,hole=F,piece=1,group=20.2,box_id=3)
coordinates(df.3.2)=c("x","y")
x <- c(+15+2*cos(2*pi/8*(0:8)))
y <- c(+15+2*sin(2*pi/8*(0:8)))
df.3.3 <- data.frame(x,y,id=20, order=1:9,hole=F,piece=1,group=20.3,box_id=3)
coordinates(df.3.3)=c("x","y")
df <- rbind(df.1,df.2,df.3.1,df.3.2,df.3.3)
df
# coordinates id order hole piece group box_id
# 1 (-10, -10) 47 1 FALSE 1 47.1 1
# 2 (-10, 10) 47 2 FALSE 1 47.1 1
# 3 (10, 10) 47 3 FALSE 1 47.1 1
# 4 (10, -10) 47 4 FALSE 1 47.1 1
# 5 (-10, -10) 47 5 FALSE 1 47.1 1
# 6 (18, -15) 48 1 FALSE 1 48.1 2
# 7 (15.92705, -12.14683) 48 2 FALSE 1 48.1 2
# 8 (12.57295, -13.23664) 48 3 FALSE 1 48.1 2
# ...
data <- data.frame(box_id=unique(df$box_id),row.names=unique(df$id))
Now, this is the code for points2polygons(...)
. With your existing SpatialPointsDataFrame, this is all you'd need.
points2polygons <- function(df,data) {
get.grpPoly <- function(group,ID,df) {
Polygon(coordinates(df[df$id==ID & df$group==group,]))
}
get.spPoly <- function(ID,df) {
Polygons(lapply(unique(df[df$id==ID,]$group),get.grpPoly,ID,df),ID)
}
spPolygons <- SpatialPolygons(lapply(unique(df$id),get.spPoly,df))
SpatialPolygonsDataFrame(spPolygons,match.ID=T,data=data)
}
spDF <- points2polygons(df,data)
plot(spDF,col=spDF$box_id+1)
library(rgdal)
writeOGR(spDF,dsn=".",layer="myShapefile", driver="ESRI Shapefile")