Cell-level functions

Introduction

The cell number is an important concept in the raster package. Raster data can be thought of as a matrix, but in a SpatRaster it is more commonly treated as a vector. Cells are numbered from the upper left cell to the upper right cell and then continuing on the left side of the next row, and so on until the last cell at the lower-right side of the raster. There are several helper functions to determine the column or row number from a cell and vice versa, and to determine the cell number for x, y coordinates and vice versa.

library(terra)
## terra 1.7.62
r <- rast(ncol=36, nrow=18)
ncol(r)
## [1] 36
nrow(r)
## [1] 18
ncell(r)
## [1] 648
rowFromCell(r, 100)
## [1] 3
colFromCell(r, 100)
## [1] 28
cellFromRowCol(r,5,5)
## [1] 149
xyFromCell(r, 100)
##       x  y
## [1,] 95 65
cellFromXY(r, cbind(0,0))
## [1] 343
colFromX(r, 0)
## [1] 19
rowFromY(r, 0)
## [1] 10

Accessing cell values

Cell values can be accessed with several methods. Use values to get all values or a single row; and valuesBlock to read a block (rectangle) of cell values.

r <- rast(system.file("ex/meuse.tif", package="terra"))
v <- values(r)
v[708:712]
## [1] NA NA NA NA NA

You can also read values using cell numbers or coordinates (xy) using the extract method.

cells <- cellFromRowCol(r, 50, 35:39)
cells
## [1] 3955 3956 3957 3958 3959
r[cells]
##   meuse
## 1   743
## 2   706
## 3   646
## 4   686
## 5   758
xy <- xyFromCell(r, cells)
xy
##           x      y
## [1,] 179780 332020
## [2,] 179820 332020
## [3,] 179860 332020
## [4,] 179900 332020
## [5,] 179940 332020
extract(r, xy)
##   meuse
## 1   743
## 2   706
## 3   646
## 4   686
## 5   758

You can also extract values using SpatialPolygons* or SpatialLines*. The default approach for extracting raster values with polygons is that a polygon has to cover the center of a cell, for the cell to be included. However, you can use argument “weights=TRUE” in which case you get, apart from the cell values, the percentage of each cell that is covered by the polygon, so that you can apply, e.g., a “50% area covered” threshold, or compute an area-weighted average.

In the case of lines, any cell that is crossed by a line is included. For lines and points, a cell that is only ‘touched’ is included when it is below or to the right (or both) of the line segment/point (except for the bottom row and right-most column).

In addition, you can use standard R indexing to access values, or to replace values (assign new values to cells) in a terra object. If you replace a value in a terra object based on a file, the connection to that file is lost (because it now is different from that file). Setting raster values for very large files will be very slow with this approach as each time a new (temporary) file, with all the values, is written to disk. If you want to overwrite values in an existing file, you can use update (with caution!)

#r[cells]
#r[1:4]
#sources(r)
#r[2:3] <- 10
#r[1:4]
#sources(r)

Note that in the above examples values are retrieved using cell numbers. That is, a raster is represented as a (one-dimensional) vector. Values can also be inspected using a (two-dimensional) matrix notation. As for R matrices, the first index represents the row number, the second the column number.

#r[1]
#r[2,2]
#r[1,]
#r[,2]
#r[1:3,1:3]
# keep the matrix structure
#r[1:3,1:3, drop=FALSE]

Accessing values through this type of indexing should be avoided inside functions as it is less efficient than accessing values via functions like values.