Nothing
#' Create, modify, and delete cell values/layers/attributes of `Spat*` objects
#'
#' @description
#'
#' `mutate()` adds new layers/attributes and preserves existing ones on a
#' `Spat*` object. `transmute()` adds new layers/attributes and drops existing
#' ones. New variables overwrite existing variables of the same name. Variables
#' can be removed by setting their value to `NULL`.
#'
#'
#' @return A `Spat*` object of the same class than `.data`. See **Methods**.
#'
#' @inheritParams select.Spat
#' @param ... <[`data-masking`][rlang::args_data_masking]> Name-value pairs.
#' The name gives the name of the layer/attribute in the output.
#'
#' @export
#' @rdname mutate.Spat
#' @name mutate.Spat
#'
#' @aliases transmute.Spat
#'
#' @importFrom dplyr mutate
#'
#' @seealso
#'
#' [dplyr::mutate()], [dplyr::transmute()] methods.
#'
#' \CRANpkg{terra} provides several ways to modify `Spat*` objects:
#'
#' - [terra::ifel()].
#' - [terra::classify()].
#' - [terra::clamp()].
#' - [terra::app()], [terra::lapp()], [terra::tapp()].
#'
#' @family single table verbs
#' @family dplyr.cols
#' @family dplyr.methods
#'
#' @section \CRANpkg{terra} equivalent:
#'
#' Some \CRANpkg{terra} methods for modifying cell values:
#' [terra::ifel()], [terra::classify()], [terra::clamp()], [terra::app()],
#' [terra::lapp()], [terra::tapp()]
#'
#' @section Methods:
#'
#' Implementation of the **generic** [dplyr::mutate()], [dplyr::transmute()]
#' functions.
#'
#' ## `SpatRaster`
#'
#' Add new layers and preserves existing ones. The result is a
#' `SpatRaster` with the same extent, resolution and crs than `.data`. Only the
#' values (and possibly the number) of layers is modified.
#'
#' `transmute()` would keep only the layers created with `...`.
#'
#' ## `SpatVector`
#'
#' The result is a `SpatVector` with the modified (and possibly renamed)
#' attributes on the function call.
#'
#' `transmute()` would keep only the attributes created with `...`.
#'
#' @examples
#'
#' library(terra)
#'
#' # SpatRaster method
#' f <- system.file("extdata/cyl_temp.tif", package = "tidyterra")
#' spatrast <- rast(f)
#'
#' mod <- spatrast %>%
#' mutate(exp_lyr1 = exp(tavg_04 / 10)) %>%
#' select(tavg_04, exp_lyr1)
#'
#' mod
#' plot(mod)
#'
#' # SpatVector method
#' f <- system.file("extdata/cyl.gpkg", package = "tidyterra")
#' v <- vect(f)
#'
#' v %>%
#' mutate(cpro2 = paste0(cpro, "-CyL")) %>%
#' select(cpro, cpro2)
mutate.SpatRaster <- function(.data, ...) {
df <- as_tbl_internal(.data)
xy <- dplyr::select(df, 1:2)
values <- dplyr::select(df, -c(1, 2))
values_mutate <- dplyr::mutate(values, ...)
# dtplyr
xy <- data.table::as.data.table(xy)
values_mutate <- data.table::as.data.table(values_mutate)
final_df <- dplyr::bind_cols(xy, values_mutate)
# To data.table and rearrange attrs
final_df <- data.table::as.data.table(final_df)
# Spatial attrs
init_att <- attributes(df)
final_att <- attributes(final_df)
spat_attrs <- init_att[setdiff(names(init_att), names(final_att))]
attributes(final_df) <- c(final_att, spat_attrs)
# Rearrange number of layers
dims <- attributes(df)$dims
dims[3] <- ncol(values_mutate)
attr(final_df, "dims") <- dims
final_rast <- as_spat_internal(final_df)
if (any(terra::has.colors(.data))) {
ctab_list <- terra::coltab(.data)
# Assign coltab by layer
l2 <- lapply(seq_len(terra::nlyr(final_rast)), function(x) {
rr <- terra::subset(final_rast, x)
if (x <= length(ctab_list)) {
ctab <- ctab_list[x]
} else {
ctab <- NULL
}
terra::coltab(rr) <- ctab
return(rr)
})
final_rast <- do.call("c", l2)
}
return(final_rast)
}
#' @export
#' @rdname mutate.Spat
mutate.SpatVector <- function(.data, ...) {
# Use own method
tbl <- as_tibble(.data)
mutated <- dplyr::mutate(tbl, ...)
# Bind
vend <- cbind(.data[, 0], mutated)
# Prepare groups
vend <- group_prepare_spat(vend, mutated)
return(vend)
}
#' @export
#' @rdname mutate.Spat
#' @importFrom dplyr transmute
transmute.SpatRaster <- function(.data, ...) {
df <- as_tbl_internal(.data)
xy <- dplyr::select(df, 1:2)
values <- dplyr::select(df, -c(1, 2))
values_transm <- dplyr::transmute(values, ...)
# dtplyr
xy <- data.table::as.data.table(xy)
values_transm <- data.table::as.data.table(values_transm)
final_df <- dplyr::bind_cols(xy, values_transm)
# To data.table and rearrange attrs
final_df <- data.table::as.data.table(final_df)
# Spatial attrs
init_att <- attributes(df)
final_att <- attributes(final_df)
spat_attrs <- init_att[setdiff(names(init_att), names(final_att))]
attributes(final_df) <- c(final_att, spat_attrs)
# Rearrange number of layers
dims <- attributes(df)$dims
dims[3] <- ncol(values_transm)
attr(final_df, "dims") <- dims
final_rast <- as_spat_internal(final_df)
# Check coltab
if (
any(terra::has.colors(.data)) && any(names(final_rast) %in% names(.data))
) {
ctab_list_init <- terra::coltab(.data)
names(ctab_list_init) <- names(.data)
namesend <- names(final_rast)
ctab_list <- ctab_list_init[namesend %in% names(.data)]
# Assign coltab by layer
l2 <- lapply(seq_len(terra::nlyr(final_rast)), function(x) {
rr <- terra::subset(final_rast, x)
if (names(rr) %in% names(ctab_list)) {
ctab <- ctab_list[match(names(rr), names(ctab_list))]
} else {
ctab <- NULL
}
terra::coltab(rr) <- ctab
return(rr)
})
final_rast <- do.call("c", l2)
}
return(final_rast)
}
#' @export
#' @rdname mutate.Spat
transmute.SpatVector <- function(.data, ...) {
# Use own method
tbl <- as_tibble(.data)
transm <- dplyr::transmute(tbl, ...)
if (ncol(transm) > 0) {
# Bind
vend <- cbind(.data[, 0], transm)
} else {
vend <- .data[, 0]
}
# Prepare groups
vend <- group_prepare_spat(vend, transm)
return(vend)
}
#' @export
dplyr::mutate
#' @export
dplyr::transmute
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.