Skip to main content

Section 1.7 The simple features framework

We’ve established now that our crime data has spatial information, which we can use to put our crimes on the map. In this section, we will introduce the simple features framework as a way to do this using R. Our task is to specify a geometry for our data, which links each unit of analysis (whether that is the point, line, or polygon) to a relevant geographical representation, allowing us to put this thing on the map.
How you add geographical information will vary with the type of information we have, but in all of these, we will use the simple features framework. The author of the sf package, Edzer Pebesma, describes simple features as a standardized way of encoding spatial vector data (points, lines, polygons). The sf package is an R package for reading, writing, handling, and manipulating simple features in R, implementing the vector data handling functionality.
Traditionally spatial analysis in R were done using the sp package which creates a particular way of storing spatial objects in R. When most packages for spatial data analysis in R and for thematic cartography were first developed sp was the only way to work with spatial data in R. There are more than 450 packages that rely on sp, making it an important part of the R ecosystem. More recently sf is changing the way that R does spatial analysis. This package provides a new way of storing spatial objects in R and most recent R packages for spatial analysis and cartography are using it as the new default. It is easy to transform sf objects into sp objects and vice versa, so that those packages that still don’t use this new format can be used. In this book we will emphasise the use of sf whenever possible. You can read more about the history of spatial packages and the sf package in the first two chapters of [115].
Features can be thought of as "things" or objects that have a spatial location or extent; they may be physical objects like a building, or social conventions like a political state. Feature geometry refers to the spatial properties (location or extent) of a feature, and can be described by a point, point set, linestring, a set of linestrings, polygon, a set of polygons, or a combination of these. The "simple" adjective of simple features refers to the property that linestrings and polygons are built from points connected by straight line segments. Features typically also have other properties (temporal properties, colour, name, measured quantity), which are called feature attributes. For more detailed insight, we recommend [234].
Let’s get started with making some maps using sf. First, make sure you install the package, and then load it with the library() function. We know that we have two columns, one for longitude and one for latitude, which pinpoint each crime event to a specific point, close to where it happened. Not quite where it happened, as the data are anonymised (more on this later), but for our purposes here, we can assume this is the location of the crime. To map these points, we can transform our ordinary dataframe into a simple features object.
To do so, we can use the st_as_sf() function from sf, into which we need to specify what we are to transform (our dataframe), where the spatial data can be found (our columns which hold the latitude and longitude information), and also what coordinate reference system the object has (see above our discussion about projections and coordinate reference systems).
Latitude and longitude coordinates specify location on the WGS 84 CRS. We can tell R that this is our CRS of choice by including its EPSG identifier as a parameter in our function. It is handy to know the more common EPSG identifiers. For example, as mentioned above, for WGS84 the EPSG identifier is 4326. For British National Grid, the identifier is 27700.
Putting it all together in practice, we can create a simple features object from our dataframe using the latitude and longitude columns:
library(sf)

crimes_sf <- st_as_sf(crimes,   #dataframe
                      #columns with coordinates:
                      coords = c("longitude", "latitude"),
                      crs = 4326)   #crs is WGS84
We can see that this is now a simple features object using the class() function to print the result "sf":
class(crimes_sf)
## [1] "sf"         "tbl_df"     "tbl"        "data.frame"
You might also notice something else that is different between "crimes" and "crimes_sf." Have a look at the dimension (hint: look in your ’Environment’ tab). In the sf object you will see that the information provided by the longitude and latitude variables has been "merged" into a new variable called geometry, that sf uses to store the kind of object we have (a point in this case) and where to locate it.