Home > OS >  Specifying layers when using rast(..., type=xyz) to convert data.frame to SpatRaster in the terra pa
Specifying layers when using rast(..., type=xyz) to convert data.frame to SpatRaster in the terra pa

Time:12-29

I have a simple csv file with lon/lat/time/values columns:

df <- data.frame(longitude=rep(c(10.5,11,12),10),
  latitude=rep(c(10.5,11,12),10),
  date= as.Date(rep(c("2012-01-01", "2012-02-01", "2012-03-01"), 10)),
  vals=rnorm(30,10,5))

I'd like to convert this to a SpatRaster using the S4 method for signature 'data.frame' rast(x, type="xyz", crs="", digits=6, extent=NULL), where each "date" would be a seperate layer.

Importing without the date works fine:

df.subset <- select(df,-date) 

tmp <- terra::rast(df.subset, type="xyz")

I've tried to split the SpatRaster by date but get a Error in .local(x, f, ...) : length(f) == nlyr(x) is not TRUE error:

split(tmp, as.factor(df$date))

I can think of an approach using a loop that

  1. splits the df by date: split(df, c("2012-01-01", "2012-02-01", "2012-03-01"))

  2. creates seperate SpatRasters for each individual date

  3. Use merge to combine individual SpatRasters with named layers

Is there a tidier way of doing this in terra?

CodePudding user response:

You can use one of the apply functions to make a list of rasters and then use rast again on this list.

library(terra)
library(dplyr)
    
# I changed the data so that different dates have many locations 
# rast complains otherwise
df <- data.frame(longitude=rep(c(10.5,11,12),10),
                                 latitude=rep(c(10.5,11,12),10),
                                 date= as.Date(c(rep("2012-01-01", 10), rep("2012-02-01", 10), rep("2012-03-01", 10))),
                                     vals=rnorm(30,10,5))
    
# A function to filter for dates 
# and remove the date column (change this if you want to keep it)
myrast <- function(df, date_to_filter) {
    df1 <- df %>% filter(date == date_to_filter) %>% select(-date)
    raster_return <- rast(x = df1, type='xyz')
    raster_return
}
    
# Iterate over all the unique dates
rr <- sapply(unique(df$date), function(d) myrast(df, d))
    
# Combine the list of raster objects
rr_all <- rast(rr)

plot(rr_all)

enter image description here

CodePudding user response:

Here is how you can use split or reshape

Example data

library(terra)
set.seed(0)
df <- data.frame(longitude=rep(seq(10,19,1), 3),
  latitude=rep(seq(10, 19,1), 3),
  date= as.Date(rep(c("2012-01-01", "2012-02-01", "2012-03-01"), each=10)),
  vals=rnorm(30,10,5))

reshape

w <- reshape(df, timevar="date", idvar=c("longitude", "latitude"), direction="wide")
x <- rast(w, type="xyz")

split

r <- split(df[,-3], df$date)
r <- lapply(r, \(i) rast(i, type="xyz")) 
r <- rast(r)

# and perhaps
time(r) <- as.Date(names(r))

r
#class       : SpatRaster 
#dimensions  : 10, 10, 3  (nrow, ncol, nlyr)
#resolution  : 1, 1  (x, y)
#extent      : 9.5, 19.5, 9.5, 19.5  (xmin, xmax, ymin, ymax)
#coord. ref. :  
#source(s)   : memory
#names       : 2012-01-01, 2012-02-01, 2012-03-01 
#min values  :    2.30025,   3.812308,   3.577003 
#max values  :   22.02327,  13.817967,  15.428847 
time (days)  : 2012-01-01 to 2012-03-01

You could also do the splitting "manually", inside the lapply loop

ud <- unique(df$date)
x <- lapply(ud, \(d) rast(df[df$date == d, -3], type="xyz"))
x <- rast(x)
names(x) <- ud
  • Related