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
GRaster
s 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 Rnumeric
type). In cases where you want aGRaster
to be treated like a float or double type raster, wrap the name of theGRaster
in thefloat()
ordouble()
functions. This is especially useful if theGRaster
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
. 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
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. 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 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 especially the GRASS manual page for module 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)
}