0

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?

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

what does the \(i) in r <- lapply(r, \(i) rast(i, type="xyz")) mean?
3

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.