Skip to content
Prev 29394 / 29559 Next

add spatraster layers by matching a dataframe column and make spatio-temporal rast

Dear Marta,


I hope I've understood properly what you're expecting.

Provided your vector values are ordered properly, you can add it as a new
layer in an existing SpatRaster using "$" as for a data.frame.
The terra::merge method may be used for different SpatRasters or between
SpatVector and data.frames but you could prepare new layers from the
original raster values using base::merge with your "ID" column.
Regarding the temporal aspect, it would mean, as I understood it, that you
should have two data.frames containing the features to be included instead
of one (for years 2001 and 2002).
Surely not the most elegant way to do it below with base R functions but it
should work.
If anyone has a more appropriate solution, I'd be greatly interested too!


# runnable example
# Make an example raster:
require(terra)
set.seed(240513)

r <- terra::rast(ncols=10, nrows=10)
values(r) <- 1:100
names(r)="ID"
# add some missing values (to make it real)
r[c(2,43,60,94)]=NA
plot(r)

# Make an example data frame (note both have an ID col to match)
d <- data.frame(
  ID=100:1,
  k=c("aa","bb"),
  e=rnorm(100,2),
  year=sample(2001:2002, 100, replace = TRUE),
  date= as.Date(rep(c("2010-01-01", "2012-02-01",
                      "2010-03-01","2010-04-01"), l=100)))
head(d)

# the terra::time is used to describe different layers of the raster which
is not appropriated in this case (one layer = one feature for one year)
# Here the values to be included in the raster are associated to different
dates so the data frame has to be splitted by year
# A different year means actually a missing value for the pixel
# the raster time index to be then defined as:
ras.time.index <- 2001:2002

col2sel <- colnames(d)[ !colnames(d) %in% c("ID", "year")]

timed.d <- do.call(merge,
              lapply(ras.time.index , function(y){
                      new.d <- d
                      new.d [!d$year %in% y, col2sel] <- NA
                      colnames(new.d)[ colnames(new.d) %in% col2sel] <-
paste(col2sel, y, sep = "_")
                      new.d <- new.d[ order(new.d$ID), !colnames(new.d)
%in% "year"]
                      return(new.d)}))

head(timed.d)


# Extract the values from the raster and make a unique index to identify
the pixel values order from original raster
ras.vals <- terra::values(r, dataframe = TRUE)
ras.val.0 <- cbind(ras.vals, index = 1:nrow(ras.val))

# Merge with d (values with missing IDs will be lost from d) while keeping
every values from original raster
ras.val.1 <- merge(ras.val.0,  timed.d, by = "ID", all.x = TRUE)
summary(ras.val.1)

# Reorder features values properly
ras.val.1 <- ras.val.1[ order(ras.val.1$index), ]

# Add these new values to the initial raster iteratively
features <- colnames(timed.d)[ !colnames(timed.d) %in% colnames(ras.val.0)]
features

for(i in 1:length(features)){

  new.values <- ras.val.1 [, features[i]]
  if(inherits(new.values, "Date")){
    new.values <- as.character(new.values)
  }
  r$new.val <- new.values
  names(r)[ names(r) %in% "new.val"] <- features[i]

}

plot(r)

# At last, define the temporal component of different layers
# To do that, distinguishing the different features seems appropriated
# Example for feature "e" layers
ras.e <-  r[[substr(names(r), 1,2) %in% "e_"]]
terra::time(ras.e, tstep="years") <- ras.time.index

plot(ras.e)

I hope this might be useful

 Best regards

Julien Rodriguez







Le lun. 13 mai 2024 ? 12:55, Marta Rufino <marta.m.rufino at gmail.com> a
?crit :