I have a spatrast with information on current velocities which I calculated from u and v components.
How can I extract points from this SPATRAST to a dataframe based on time and spatial matches?
code for recreating example data:
library(stars)
library(lubridate)
library(terra)
# create a datetime vector holding 364 entries at one hour intervals####
datetime <- seq(as.POSIXct("2020-01-01 00:00:00"), as.POSIXct("2020-01-17 00:00:00"), by="hour")
datetime <- datetime[1:364]
# Create a sample rast ####
v <- rast(ncol=37, nrow=74, nlyr=364, extent=ext(-6.3875, -5.4875, 52.2375, 54.0625),
crs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs+ towgs84=0,0,0", time=datetime)
v <- init(v, runif)
# Create a sample df
time <- as.POSIXct(c("2020-01-01 15:21:00", "2020-01-14 08:01:00", "2020-01-16 21:19:00"))
lat <- c("53.92265", "52.86578", "53.38290")
long <-c("-6.026689", "-5.819075", "-6.028343")
sighting <- c("1", "0", "1")
df <- data.frame(sighting, lat, long, time)
DF<- st_as_sf(df, coords = c("long", "lat"))
DF = st_set_crs(DF, "EPSG:4326")
#DF = st_transform(DF, 2157) # CRS ITM
I tired to use st_extract from stars:
# save spatrast as a stars object
v.star <-st_as_stars(v)
#v.star = st_transform(v.star, 2157) # CRS ITM
# extract current velocities to DF
DF$cur_vel <- st_extract(v.star, DF, time_column = "time")
However, this returns the DF with time and geometry from the DF repeated and a cur_vel column with NA's:
It seems the function requires an exact match?
To circumvent this I used data.table to match the times from DF to the nearest time in the raster
# Drop geom of DF and make a data.table
DF <- st_transform(DF, 4326)
DF <- cbind(as.data.table(st_drop_geometry(DF)),
st_coordinates(DF))
# save all the times from the spatrast in a data.table
time <- time(v)
DT = data.table(
ID = 1:364,
time = time
)
# Extract the nearest rast times (DT/v) to the times in the DF
DF.rast.time <- DF[, c("RASTtime") :=
DT[DF, on = c("time"), roll = 'nearest', .(x.time)]][]
This produces the following data frame
And I then extracted the current velocity values from the raster but using the new RASTtimes in DF:
# save DF.rast.time as an sf object again
DF.rast.time<- st_as_sf(DF.rast.time, coords = c("X", "Y"))
DF.rast.time = st_set_crs(DF.rast.time, "EPSG:4326")
# extract current velocities to DF
DF.rast.time$cur_vel <- st_extract(v.star, DF.rast.time, time_column = "RASTtime") %>%
st_as_sf()
This produced the result I was looking for:
However, is it possible to stop the replicate columns of RASTtime and geometry from appearing in this new dataframe?
Also, is there a more straightforward way to find nearest matches in time between a dataframe and a raster?