You can find a more complete demonstration of working with spatial object in R here: https://mgimond.github.io/Spatial/reading-and-writing-spatial-data-in-r.html
Build SpatialPointsDataframe
Dealing with points is relatively easy compared to polygons or lines
library(raster) library(sp) library(rgdal) library(sf) # Approach 1 npts = 50 pts_df = data.frame(id=1:npts,x=rnorm(npts)*1000+10e6, y=rnorm(npts)*1000+10e6 , z=rnorm(npts)) coordinates(pts_df) = ~x+y # Approach 2 npts = 50 pts_df = data.frame(id=1:npts,x=rnorm(npts)*1000+10e6, y=rnorm(npts)*1000+10e6 , z=rnorm(npts)) coordinates(pts_df) = pts_df[,c("x","y")] pts_df plot(pts_df) spplot(pts_df,zcol="z")
Add projection to pts_df and write to a shapefile.
You will need to figure out your projection string if you don't already have it e.g. you can search here https://www.spatialreference.org/
I have selected this projection for this toy example https://www.spatialreference.org/ref/epsg/3692/proj4/
See here for more details on projections in R: https://www.nceas.ucsb.edu/sites/default/files/2020-04/OverviewCoordinateReferenceSystems.pdf
some_proj4 = "+proj=lcc +lat_1=47.33333333333334 +lat_2=45.83333333333334 +lat_0=45.33333333333334 +lon_0=-120.5 +x_0=500000.0001016001 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +to_meter=0.3048006096012192 +no_defs" proj4string(pts_df) = some_proj4 #shapefiles are not great, but they are the most common spatial objects (field name restrictions, file size limitations, proprietary, etc.) if(file.exists("c:/temp/example_pts.shp")) unlink("c:/temp/example_pts.shp",force=T) rgdal::writeOGR(pts_df,dsn="c:/temp","example_pts1", driver = "ESRI Shapefile", overwrite_layer = T) #A better option is the open source geopackage (it's like an ESRI file geodatabase). Unfortunately rgdal has pretty lousy support for geopackages as far as I can tell, e.g it cannot append. if(file.exists("c:/temp/demo_geopackage.gpkg")) try(unlink("c:/temp/demo_geopackage.gpkg",force=T)) rgdal::writeOGR(pts_df,dsn="c:/temp/demo_geopackage.gpkg","example_pts1", driver = "GPKG") #the sf package does a better job, but you have to convert from sp to sf first... It seems like sf objects are a better data model (basically an R data frame), but most spatial packages in R still use sp objects. pts_df_sf = sf::st_as_sf(pts_df) #this add a new layer to the geopackage - not possible with rgdal (for geopackages) if(file.exists("c:/temp/demo_geopackage1.gpkg")) try(unlink("c:/temp/demo_geopackage1.gpkg",force=T)) sf::st_write(pts_df_sf,dsn="c:/temp/demo_geopackage1.gpkg", "example_pts2", driver="GPKG") #we can even append new rows to an existing object using sf - definitely not possible with rgdal (for geopackages) pts_df_sf2 = pts_df_sf row.names(pts_df_sf2 ) = as.numeric(row.names(pts_df_sf )) + max(as.numeric(row.names(pts_df_sf ))) pts_df_sf2$id = pts_df_sf$id + max(pts_df_sf$id) sf::st_write(pts_df_sf2,dsn="c:/temp/demo_geopackage1.gpkg", "example_pts2", driver="GPKG",append=T) #verify that append works pts_df_sf3 = sf::read_sf(dsn="c:/temp/demo_geopackage1.gpkg", "example_pts2") #notice that pts_df_sf3 has npts*2 records ... nrow(pts_df_sf) nrow(pts_df_sf2) nrow(pts_df_sf3) knitr::kable(tail(pts_df_sf3,10)) #DT::datatable(pts_df_sf3)
buffer points to create polygons this is an easy way to make a SpatialPolygonsDataFrame
bf1 = raster::buffer(pts_df , dissolve=FALSE) bf1
Create SpatialPolygonsDataFrame
Making a SpatialPolygonsDataFrame manually is a lot of work
now lets make a circle
#number of vertices nvtx = 100 #split circle into nvtx slices - add zero to end to close polygon rads0 = c(seq(0,2*pi,length.out = nvtx),0) #compute x,y coordinates radius0 = 100 xcds = radius0*cos(rads0) ycds = radius0*sin(rads0) plycds = data.frame(x=xcds, y=ycds) #verify that we built a circle plot(plycds,asp=1,type="l") #build sp objects ply1a = sp::Polygon(plycds) ply1b = sp::Polygon(plycds+50) ply2a = sp::Polygons(list(ply1a),ID=1) ply2b = sp::Polygons(list(ply1b),ID=2) ply2c = sp::Polygons(list(ply1a,ply1b),ID=1) #same data, two ways to store it ply3a = SpatialPolygons(list(ply2a,ply2b)) ply3b = SpatialPolygons(list(ply2c)) #take a look ply3a plot(ply3a) ply3b plot(ply3b) #finish the object ply4a = SpatialPolygonsDataFrame( ply3a , data.frame(id=1:length(ply3a))) ply4b = SpatialPolygonsDataFrame( ply3b , data.frame(id=1:length(ply3b))) #look at final products ply4a ply4b par(mfrow=c(1,2)) plot(ply4a,col=ply4a@data[,"id"]) plot(ply4b,col=ply4b@data[,"id"]) #pretty interesting, in the second approach, R interprets the overlap as void...
Create SpatialLinesDataFrame
Lines use a similar process to polygons. I have taken a shortcut here and based my example on the sp vignette.
# based on example from the sp vignette: l1 = cbind(c(1,2,3),c(3,2,2)) rownames(l1) = letters[1:3] l1a = cbind(l1[,1]+.05,l1[,2]+.05) rownames(l1a) = letters[1:3] l2 = cbind(c(1,2,3),c(1,1.5,1)) rownames(l2) = letters[1:3] Sl1 = Line(l1) Sl1a = Line(l1a) Sl2 = Line(l2) S1 = Lines(list(Sl1, Sl1a), ID="a") S2 = Lines(list(Sl2), ID="b") Sl = SpatialLines(list(S1,S2)) summary(Sl) plot(Sl, col = c("red", "blue")) #create sp dataframe sldf = SpatialLinesDataFrame(Sl, data.frame(id = names(Sl), someY=rnorm(length(Sl)),row.names=names(Sl)), match.ID = TRUE) #plot spatial objects sp::spplot(sldf,"someY",lwd=3)
buffer lines to make polygons
lnbuff1 = raster::buffer(sldf,.5,dissolve=F) lnbuff2 = raster::buffer(sldf,.5,dissolve=T) #or lnbuff1 = rgeos::gBuffer(sldf,width=.5,byid = F ) lnbuff2 = rgeos::gBuffer(sldf,width=.5,byid = T) #look at results lnbuff1 lnbuff2 par(mfrow=c(1,2)) raster::plot(lnbuff1) raster::plot(sldf,col=1:length(sldf),add=T) raster::plot(lnbuff2) raster::plot(sldf,col=1:length(sldf),add=T)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.