I have a data frame with a bunch of polygons, several points per polygon. How can I convert it to a SpatialPolygonsDataFrame
object?
Here's my data frame:
> buildings_df
lon lat id
1 96.13597 16.83363 convocation_hall
2 96.13580 16.83315 convocation_hall
3 96.13631 16.83298 convocation_hall
4 96.13656 16.83351 convocation_hall
5 96.13400 16.83104 judson_church
6 96.13392 16.83073 judson_church
7 96.13432 16.83064 judson_church
8 96.13444 16.83085 judson_church
9 96.13596 16.83074 the_library
10 96.13586 16.83044 the_library
11 96.13615 16.83035 the_library
12 96.13626 16.83065 the_library
13 96.13599 16.83073 the_library
This can be reproduced with:
> dput(buildings_df)
structure(list(lon = c(96.135972, 96.1358, 96.136315, 96.136562,
96.133997, 96.133922, 96.134319, 96.134437, 96.135961, 96.135864,
96.136154, 96.136261, 96.135993), lat = c(16.833625, 16.833153,
16.832978, 16.833512, 16.831038, 16.830729, 16.830637, 16.830853,
16.83074, 16.830442, 16.83035, 16.830647, 16.830729), id = structure(c(1L,
1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), .Label = c("convocation_hall",
"judson_church", "the_library"), class = "factor")), .Names = c("lon",
"lat", "id"), row.names = c(NA, -13L), class = "data.frame")
From this data.frame, I then convert it to a list, then to polygons, then to a SpatialPolygons object
# make a list
buildings_list <- split(buildings_df, buildings_df$id)
# only want lon-lats in the list, not the names
buildings_list <- lapply(buildings_list, function(x) { x["id"] <- NULL; x })
# make data.frame into spatial polygon, cf. http://jwhollister.com/iale_open_science/2015/07/05/03-Spatial-Data-In-R/
# create SpatialPolygons Object, convert coords to polygon
ps <- sapply(buildings_list, Polygon)
# add id variable
p1 <- Polygons(ps, ID = 1)
# create SpatialPolygons object
my_spatial_polys <- SpatialPolygons(list(p1), proj4string = CRS("+proj=longlat +datum=WGS84") )
# let's see them
plot(my_spatial_polys)
So far so good:
And each of the polygons seems to be in there…
> str(my_spatial_polys)
Formal class 'SpatialPolygons' [package "sp"] with 4 slots
..@ polygons :List of 1
.. ..$ :Formal class 'Polygons' [package "sp"] with 5 slots
.. .. .. ..@ Polygons :List of 3
.. .. .. .. ..$ convocation_hall:Formal class 'Polygon' [package "sp"] with 5 slots
.. .. .. .. .. .. ..@ labpt : num [1:2] 96.1 16.8
.. .. .. .. .. .. ..@ area : num 3.08e-07
.. .. .. .. .. .. ..@ hole : logi FALSE
.. .. .. .. .. .. ..@ ringDir: int 1
.. .. .. .. .. .. ..@ coords : num [1:5, 1:2] 96.1 96.1 96.1 96.1 96.1 ...
.. .. .. .. ..$ judson_church :Formal class 'Polygon' [package "sp"] with 5 slots
.. .. .. .. .. .. ..@ labpt : num [1:2] 96.1 43.3
.. .. .. .. .. .. ..@ area : num 0.0204
.. .. .. .. .. .. ..@ hole : logi TRUE
.. .. .. .. .. .. ..@ ringDir: int -1
.. .. .. .. .. .. ..@ coords : num [1:5, 1:2] 96.1 96.1 96.1 96.1 96.1 ...
.. .. .. .. ..$ the_library :Formal class 'Polygon' [package "sp"] with 5 slots
.. .. .. .. .. .. ..@ labpt : num [1:2] 96.1 43.3
.. .. .. .. .. .. ..@ area : num 0.00512
.. .. .. .. .. .. ..@ hole : logi TRUE
.. .. .. .. .. .. ..@ ringDir: int -1
.. .. .. .. .. .. ..@ coords : num [1:6, 1:2] 96.1 96.1 96.1 96.1 96.1 ...
.. .. .. ..@ plotOrder: int [1:3] 1 2 3
.. .. .. ..@ labpt : num [1:2] 96.1 16.8
.. .. .. ..@ ID : chr "1"
.. .. .. ..@ area : num 0.0302
..@ plotOrder : int 1
..@ bbox : num [1:2, 1:2] 96.1 16.8 96.1 16.8
.. ..- attr(*, "dimnames")=List of 2
.. .. ..$ : chr [1:2] "x" "y"
.. .. ..$ : chr [1:2] "min" "max"
..@ proj4string:Formal class 'CRS' [package "sp"] with 1 slot
.. .. ..@ projargs: chr "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"
But they don't seem to be grouped in the way I'm expecting. When I try to set three ID variables, I get an error. How can I get the SpatialPolygons to have three polygons, each with its own ID?
Best Answer
One solution is to change
p1 <- Polygons(ps, ID = 1)
to anapply
-like function so that thePolygons()
function operates individually on each of the polygons in theps
object.Then we can create the
SpatialPolygonsDataFrame
with the IDs as expected, one unique ID per polygon: