2.2 Simple feature geometry, simple feature geometry list-column, and simple feature
Here, we learn how different types of sfg
are constructed. We also learn how to create sfc
and sf
from sfg
from scratch.34
2.2.1 Simple feature geometry (sfg
)
The sf
package uses a class of sfg
(simple feature geometry) objects to represent a geometry of a single geometric feature (say, a city as a point, a river as a line, county and school district as polygons). There are different types of sfg
s. Here are some example feature types that we commonly encounter as an economist35:
POINT
: area-less feature that represents a point (e.g., well, city, farmland)LINESTRING
: (e.g., a tributary of a river)MULTILINESTRING
: (e.g., river with more than one tributary)POLYGON
: geometry with a positive area (e.g., county, state, country)MULTIPOLYGON
: collection of polygons to represent a single object (e.g., countries with islands: U.S., Japan)
POINT
is the simplest geometry type and is represented by a vector of two36 numeric values. An example below shows how a POINT
feature can be made from scratch:
#--- create a POINT ---#
<- st_point(c(2, 1)) a_point
The st_point()
function creates a POINT
object when supplied with a vector of two numeric values. If you check the class of the newly created object,
#--- check the class of the object ---#
class(a_point)
[1] "XY" "POINT" "sfg"
you can see that it’s indeed a POINT
object. But, it’s also an sfg
object. So, a_point
is an sfg
object of type POINT
.
A LINESTRING
objects are represented by a sequence of points:
#--- collection of points in a matrix form ---#
<- rbind(c(2, 3), c(3, 4), c(3, 5), c(1, 5))
s1
#--- see what s1 looks like ---#
s1
[,1] [,2]
[1,] 2 3
[2,] 3 4
[3,] 3 5
[4,] 1 5
#--- create a "LINESTRING" ---#
<- st_linestring(s1)
a_linestring
#--- check the class ---#
class(a_linestring)
[1] "XY" "LINESTRING" "sfg"
s1
is a matrix where each row represents a point. By applying st_linestring()
function to s1
, you create a LINESTRING
object. Let’s see what the line looks like.
plot(a_linestring)
As you can see, each pair of consecutive points in the matrix are connected by a straight line to form a line.
A POLYGON
is very similar to LINESTRING
in the manner it is represented.
#--- collection of points in a matrix form ---#
<- rbind(c(0, 0), c(3, 0), c(3, 2), c(2, 5), c(1, 3), c(0, 0))
p1
#--- see what s1 looks like ---#
p1
[,1] [,2]
[1,] 0 0
[2,] 3 0
[3,] 3 2
[4,] 2 5
[5,] 1 3
[6,] 0 0
#--- create a "POLYGON" ---#
<- st_polygon(list(p1))
a_polygon
#--- check the class ---#
class(a_polygon)
[1] "XY" "POLYGON" "sfg"
#--- see what it looks like ---#
plot(a_polygon)
Just like the LINESTRING
object we created earlier, a POLYGON
is represented by a collection of points. The biggest difference between them is that we need to have some positive area enclosed by lines connecting the points. To do that, you have the the same point for the first and last points to close the loop: here, it’s c(0,0)
. A POLYGON
can have holes in it. The first matrix of a list becomes the exterior ring, and all the subsequent matrices will be holes within the exterior ring.
#--- a hole within p1 ---#
<- rbind(c(1, 1), c(1, 2), c(2, 2), c(1, 1))
p2
#--- create a polygon with hole ---#
<- st_polygon(list(p1, p2))
a_plygon_with_a_hole
#--- see what it looks like ---#
plot(a_plygon_with_a_hole)
You can create a MULTIPOLYGON
object in a similar manner. The only difference is that you supply a list of lists of matrices, with each inner list representing a polygon. An example below:
#--- second polygon ---#
<- rbind(c(4, 0), c(5, 0), c(5, 3), c(4, 2), c(4, 0))
p3
#--- create a multipolygon ---#
<- st_multipolygon(list(list(p1, p2), list(p3)))
a_multipolygon
#--- see what it looks like ---#
plot(a_multipolygon)
Each of list(p1,p2)
and list(p3)
represents a polygon. You supply a list of these lists to the st_multipolygon()
function to make a MULTIPOLYGON
object.
2.2.2 Create simple feature geometry list-column (sfc
) and simple feature (sf
) from scratch
To make a simple feature geometry list-column (sfc
), you can simply supply a list of sfg
to the st_sfc()
function as follows:
#--- create an sfc ---#
<- st_sfc(list(a_point, a_linestring, a_polygon, a_multipolygon)) sfc_ex
To create an sf
object, you first add an sfc
as a column to a data.frame
.
#--- create a data.frame ---#
<- data.frame(name = c("A", "B", "C", "D"))
df_ex
#--- add the sfc as a column ---#
$geometry <- sfc_ex
df_ex
#--- take a look ---#
df_ex
name geometry
1 A POINT (2 1)
2 B LINESTRING (2 3, 3 4, 3 5, ...
3 C POLYGON ((0 0, 3 0, 3 2, 2 ...
4 D MULTIPOLYGON (((0 0, 3 0, 3...
At this point, it is not yet recognized as an sf
by R yet.
#--- see what it looks like (this is not an sf object yet) ---#
class(df_ex)
[1] "data.frame"
You can register it as an sf
object using st_as_sf()
.
#--- let R recognize the data frame as sf ---#
<- st_as_sf(df_ex)
sf_ex
#--- see what it looks like ---#
sf_ex
Simple feature collection with 4 features and 1 field
Geometry type: GEOMETRY
Dimension: XY
Bounding box: xmin: 0 ymin: 0 xmax: 5 ymax: 5
CRS: NA
name geometry
1 A POINT (2 1)
2 B LINESTRING (2 3, 3 4, 3 5, ...
3 C POLYGON ((0 0, 3 0, 3 2, 2 ...
4 D MULTIPOLYGON (((0 0, 3 0, 3...
As you can see sf_ex
is now recognized also as an sf
object.
#--- check the class ---#
class(sf_ex)
[1] "sf" "data.frame"
Creating spatial objects from scratch yourself is an unnecessary skill for many of us as economists. But, it is still good to know the underlying structure of the data. Also, occasionally the need arises. For example, I had to construct spatial objects from scratch when I designed on-farm randomized nitrogen trials. In such cases, it is of course necessary to understand how different types of
sfg
are constructed, createsfc
from a collection ofsfg
s, and then create ansf
from ansfc
.↩︎You will hardly see the other geometry types: MULTIPOINT and GEOMETRYCOLLECTION. You may see GEOMETRYCOLLECTION after intersecting two spatial objects. You can see here if you are interested in learning what they are.↩︎
or three to represent a point in the three-dimensional space↩︎