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 somewhat different from terra::app(). The function to be applied must be written as a character string. For example, if the GRaster 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". Note that the name of a GRaster is given by names()–this can be different from the name of the object in R.
The app() function will automatically check for GRaster 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
GRasters havenames(). The function matches on these, not the name of the variable you use in R for theGRaster.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; commensurate with the Rnumerictype). In cases where you want aGRasterto be treated like a float or double type raster, wrap the name of theGRasterin thefloat()ordouble()functions. This is especially useful if theGRastermight be assumed to be theCELLtype because it only contains integer values. You can get the data type of a raster usingdatatype()with thetypeargument set toGRASS. You can change the data type of aGRasterusingas.int(),as.float(), andas.doub(). Note that categorical rasters are reallyCELL(integer) rasters with an associated "levels" table. You can also change aCELLraster to aFCELLraster by adding then subtracting a decimal value, as inx - 0.1 + 0.1. Seevignette("GRasters", package = "fasterRaster").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
GRasterwith 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 thatxandyare forbidden names :(
The help page for GRASS tool
r.mapcalcwill be especially helpful. You can see this page usinggrassHelp("r.mapcalc").- 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 typefloatif 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 especially the GRASS manual page for tool r.mapcalc (see grassHelp("r.mapcalc"))
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()
# We can also get the same 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:
fun <- "= x1 + x3"
app(x, fun = fun, datatype = "float") # output is floating-point
app(x, fun = fun, datatype = "integer") # output is integer
# Some functions override the "datatype" argument:
fun <- "= sin(x2)"
app(x, fun = fun, datatype = "integer")
# Make a raster with random values [1:4], with equal probability of each:
fun <- "= round(rand(0.5, 4.5))"
rand <- app(elev, fun = fun)
rand
freqs <- freq(rand) # cell frequencies
print(freqs)
}
