app()
applies a function to a set of "stacked" rasters. It is similar to the terra::app()
and terra::lapp()
functions.
appFuns()
provides a table of GRASS functions that can be used by app()
and their equivalents in R.
appCheck()
tests whether a formula supplied to app()
has any "forbidden" function calls.
The app()
function operates in a manner slightly different from terra::app()
. The function to be applied must be written as a character string. For example, if the raster had layer names "x1
" and "x2
", then the function might be like "= max(sqrt(x1), log(x2))"
. Rasters cannot have the same names as functions used in the formula. In this example, the rasters could not be named "max", "sqrt", or "log".
The app()
function will automatically check for raster names that appear also to be functions that appear in the formula. However, you can check a formula before running app()
by using the appCheck()
function. You can obtain a list of app()
functions using appFuns()
. Note that these are sometimes different from how they are applied in R.
Tips:
Make sure your
GRaster
s havenames()
. The function matches on these, not the name of the variable you use in R for theGRaster
.In GRASS, use
null()
instead ofNA
, and useisnull()
instead ofis.na()
.If you want to calculate values using while ignoring
NA
(ornull
) values, see the functions that begin withn
(likenmean
).Be mindful of the data type that a function returns. In GRASS, these are
CELL
(integer),FCELL
(floating point values–precise to about the 7th decimal place), andDCELL
(double-floating point values–precise to about the 15th decimal place). In cases where you want to datatype a raster to be treated like a float or double data type raster, wrap the raster in thefloat()
ordouble()
functions to datatype it is treated as such. This is especially useful if the raster might be assumed to be theCELL
type because it only contains integer values. You can get the data type of a raster usingdatatype()
with thetype
argument set toGRASS
. You can change the data type of aGRaster
usingas.int()
,as.float()
, andas.doub()
. Note that categorical rasters are reallyCELL
(integer) rasters with an associated "levels" table. You can also change aCELL
raster to aFCELL
raster by adding then subtracting a decimal value, as inx - 0.1 + 0.1
.The
rand()
function returns integer values by default. If you want non-integer values, use the tricks mentioned above to datatype non-integer values. For example, if you want uniform random values in the range between 0 and 1, use something like= float(rand(0 + 0.1, 1 + 0.1) - 0.1)
.
Usage
# S4 method for class 'GRaster'
app(x, fun, datatype = "auto", seed = NULL)
appFuns(warn = TRUE)
# S4 method for class 'GRaster,character'
appCheck(x, fun, msgOnGood = TRUE, failOnBad = TRUE)
Arguments
- x
A
GRaster
with one or more named layers.- fun
Character: The function to apply. This must be written as a character string that follows these rules:
It must use typical arithmetic operators like
+
,-
,*
,/
and/or functions that can be seen usingappFuns(TRUE)
.The
names()
of the rasters do not match any of the functions in theappFuns(TRUE)
table. Note thatx
andy
are forbidden names :(
The help page for GRASS module
r.mapcalc
will be especially helpful.- datatype
Character: This ensures that rasters are treated as a certain type before they are operated on. This is useful when using rasters that have all integer values, which GRASS can assume represent integers, even if they are not supposed to. In this case, the output of operations on this raster might be an integer if otherwise not corrected. Partial matching is used, and options include:
"integer"
: Force all rasters to integers by truncating their values. The output may still be of typefloat
if the operation creates non-integer values."float"
: Force rasters to be considered floating-point values."double"
: Force rasters to be considered double-floating point values."auto"
(default): Ensure that rasters are represented by their nativedatatype()
(i.e., "CELL" rasters as integers, "FCELL" rasters as floating-point, and "DCELL" as double-floating point).
- seed
Numeric integer vector or
NULL
(default): A number for the random seed. Used only forapp()
functionrand()
, that generates a random number. IfNULL
, a seed will be generated. Defining the seed is useful for replicating a raster made withrand()
. This must be an integer!- warn
Logical (function
appFuns()
): IfTRUE
(default), display a warning whenallFuns()
is not called interactively.- msgOnGood
Logical (function
appCheck()
): IfTRUE
(default), display a message if no overt problems with the raster names and formula are detected.- failOnBad
Logical (function
appCheck()
): IfTRUE
(default), fail if overt problems with raster names and the formula are detected.
See also
terra::app()
, terra::lapp()
, subst()
, classify()
, and modules r.mapcalc
and r.mapcalc.simple
in GRASS.
Examples
if (grassStarted()) {
# Setup
library(terra)
# Elevation raster
madElev <- fastData("madElev")
# Convert SpatRaster to a GRaster:
elev <- fast(madElev)
# Create a "stack" of rasters for us to operate on:
x <- c(elev, elev^2, sqrt(elev))
# Demonstrate check for badly-named rasters:
names(x) <- c("cos", "asin", "exp")
fun <- "= cos / asin + exp"
appCheck(x, fun, failOnBad = FALSE)
# Rename rasters acceptable names and run the function:
names(x) <- c("x1", "x2", "x3")
fun <- "= (x1 / x2) + x3"
appCheck(x, fun, failOnBad = FALSE)
app(x, fun = fun)
# This is the same as:
(x[[1]] / x[[2]]) + x[[3]]
# We can view a table of app() functions using appFuns():
appFuns(FALSE) # Change to TRUE to see a Shiny version.
# We can also get the table using:
data(appFunsTable)
# Apply other functions:
fun <- "= median(x1 / x2, x3, x1 * 2, cos(x2))"
app(x, fun = fun)
fun <- "= round(x1) * tan(x2) + log(x3, 10)"
app(x, fun = fun)
# Demonstrate effects of data type. The "+" sign does not guarantee
# output is of a given type, and the rasters are coerced to integers before
# the operation is conducted in the second function.
fun <- "= x1 + x3"
app(x, fun = fun, datatype = "float") # output is floating-point
app(x, fun = fun, da = "integer") # output is integer
# Some functions override the "datatype" argument. In this case, the output will
# not be an integer because the sin() function returns a float value.
fun <- "= sin(x2)"
app(x, fun = fun, datatype = "integer")
# Make a raster with random numbers between 1 and 4, with equal probability
# of each:
fun <- "= round(rand(0.5, 4.5))"
rand <- app(elev, fun = fun)
rand
freq(rand) # cell frequencies
}