4.4 Turning a raster object into a data.frame

When creating maps using ggplot2() from a SpatRaster or Raster\(^*\) object, it is necessary to first convert it to a data.frame (see Chapter 8.2). You can use the as.data.frame() function with xy = TRUE option to construct a data.frame where each row represents a single cell that has cell values for each layer and its coordinates (the center of the cell).

#--- converting to a data.frame ---#
IA_cdl_df <- as.data.frame(IA_cdl_stack_sr, xy = TRUE) # this works with Raster* objects as well

#--- take a look ---#
head(IA_cdl_df)
       x       y Layer_1 Layer_1.1
1 -52080 2288280       0         0
2 -52050 2288280       0         0
3 -52020 2288280       0         0
4 -51990 2288280       0         0
5 -51960 2288280       0         0
6 -51930 2288280       0         0

Note: I have seen cases where a raster object is converted to a data.frame and then to ‘sf’ for the purpose of interacting it with polygons using st_join() to extract and assign cell values for the polygons (see Chapter 3 for this type of operation). This is, however, not generally recommended for two reasons. First of all, it is much slower than using functions that work on a raster object and polygons directly to extract values for the polygons, such as terra::extract() or exactextractr::exact_extract(), which are introduced in Chapter 5. This is primarily because converting a raster object to a data.frame() is very slow. Second, once a raster data object is converted to a point sf data, one can no longer weight cell values according to the degree of their overlaps with the target polygons. The only case I have found the conversion beneficial (or simply necessary) is to create a map using ggplot() from a raster object (the tmap package can work directly with raster objects.). While the desire to work with a data.frame is understandable as we are very comfortable with working on a data.frame, it is very likely that the conversion to a data.frame is not only unnecessary, but also inefficient71.


  1. If you are aware of cases where a conversion to data.frame is beneficial, please let me know. I will put them here.↩︎