簡體   English   中英

如何從年度柵格圖層堆棧中提取值並使用時間最接近的柵格

[英]How to extract values from annual raster layer stack and use the raster that is closest in time

我有許多帶有時間日期戳的點位置和 18 個柵格層,每個柵格層包含 2002 年至 2019 年的年度 NDVI 值。我想從類似於位置年份的年份柵格層中提取這些位置的值時間戳。

例子:

location1 時間戳 12.04.2003 --> 從柵格層 2003 中提取值
location2 時間戳 12.06.2012 --> 從柵格層 2012 中提取值

這是我的位置數據示例 (EPSG 3035):

  X id areas sex      x_      y_ case                time
1 1  1    13   f 4141879 2762606    1 2010-11-16 00:59:00
2 2  1    13   f 4142395 2759956    1 2010-11-16 21:59:00
3 3  1    13   f 4143634 2761615    1 2010-11-17 04:59:00
4 4  1    13   f 4143171 2761593    1 2010-11-17 11:59:00
5 5  1    13   f 4144488 2762547    1 2010-11-17 18:59:00
6 6  1    13   f 4143885 2761944    1 2010-11-18 08:59:00

首先,我創建了一個包含所有 18 個柵格圖層的柵格堆棧,並為每個圖層添加了日期:

#create raster stack NDVI 
setwd("E:/MA_2Try/annual_NDVI/average")
grids <- list.files("E:/MA_2Try/annual_NDVI/average" , pattern = "*.tif$")
NDVI_stack=stack(grids)

#Add years to stack
dt<-as.data.frame(
  as.POSIXct(c('2002-01-01','2003-01-01','2004-01-01','2005-01-01','2006-01-01',
               '2007-01-01','2008-01-01','2009-01-01','2010-01-01','2011-01-01',
               '2012-01-01','2013-01-01','2014-01-01','2015-01-01','2016-01-01',
               '2017-01-01','2018-01-01','2019-01-01'))) 

NDVI_stack <- setZ(NDVI_stack, dt[,1], "SampleDate")

這是柵格 [[1]] 的結果信息

> NDVI_stack[[1]]
class      : RasterLayer 
dimensions : 4125, 5503, 22699875  (nrow, ncol, ncell)
resolution : 250, 250  (x, y)
extent     : 3530500, 4906250, 2229250, 3260500  (xmin, xmax, ymin, ymax)
crs        : +proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +units=m +no_defs 
source     : ndvi_average_2002.tif.tif 
names      : ndvi_average_2002.tif 
SampleDate : 2002-01-01 

我怎樣才能做到這一點?

你可以嘗試這樣的事情:

library(raster)
library(sf)
rast <- raster::raster(matrix(1:100, ncol=10), xmn=0, ymn=0, xmx=10, ymx=10)
s <- stack(rast,rast/100,rast*100)
s <- setZ(s, c('2010-01-01','2011-01-01','2013-01-01'), "SampleDate")

pt1 = st_point(c(0,1))
pt2 = st_point(c(1,1))
d = data.frame(id = 1:2,sex=c("m","f"),date = c("2010-11-16 00:59:00","2011-11-16 21:59:00"))
d$geom = st_sfc(pt1, pt2)
df = st_as_sf(d)


myex <- function(rst,point){
  ex <- as.list(1:nrow(point))
  for (i in 1:nrow(point)) {
    year_p <- as.integer(lubridate::year(point[i,]$date))
    diff <- abs(year_p-as.integer(lubridate::year(unlist(rst@z))))
    index <- which(diff==min(diff))
    ex[[i]] <- raster::extract(rst[[index]],point[i,],include_cols=colnames(point))
  }
  ex <- as.data.frame(do.call(rbind,ex))
  ex$id <- point$id
  return(ex)
}

myex(s,df)

output 看起來像這樣:

    V1 id
1 10.0  1
2  0.2  2

這個想法是選擇點日期和圖層日期之間差異最小的圖層並將其用於提取。 這里我使用了一個for循環,但也可以使用lapply或其並行版本之一(例如snowfall::sfLaplly )。 此外,如果您在點周圍創建一個小緩沖區,則可以用exactextract::exact_extract替換raster::extract ,這樣會更快

這是使用terra執行此操作的方法(但應該很容易針對raster進行調整)

示例數據

library(terra)
s <- rast(system.file("ex/logo.tif", package="terra"))   
names(s) <- 2010:2012
pts <- matrix(c(14.53, 70.41, 12.93, 53.8, 60.21, 47.41), ncol=2, byrow=TRUE)
time <- as.POSIXct(c("2011-11-16 00:59:00", "2010-01-16 00:59:00", "2010-11-16 00:59:00"))

從時間戳中獲取所需的層(年)並將它們與層匹配。 如果月份 > 六月,一個簡單的方法是將年份四舍五入:

y <- format(time, format='%Y') |> as.integer()
m <- format(time, format='%m') |> as.integer()
y <- y + (m > 6)
y
#[1] 2012 2010 2011
 

現在使用提取物

e <- extract(s, vect(pts), layer=as.character(y))
e
#  ID layer value
#1  1  2012   253
#2  2  2010    73
#3  3  2011    14

使用raster ,您可以像這樣執行最后一步:

ee <- extract(s, pts)
ee
#  2010 2011 2012
#1  255  255  253
#2   73   74   60
#3    6   14   27

j <- match(y, names(s))
j
#[1] 3 1 2
     
ee[cbind(1:nrow(ee), j)]
#[1] 253  73  14

但請注意,光柵可能會在圖層名稱前加上“X”,它們以 0 到 9 之間的字符開頭。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM