堆叠栅格并计算每个像素的最大值,然后将该值保留在R中的其余图层中

cnh2zyt3  于 2023-01-22  发布在  其他
关注(0)|答案(2)|浏览(180)

我有181每日ndvi光栅堆叠。我想找到每个像素的峰值,然后分配峰值到其余的。原始数据曲线:

这就是我想要的

这个结果是为单个像素。我已经在excel中做了,但要创建一个代码中的R轻松。现在每个像素达到峰值在不同的日期(所以不同的层堆栈)。
我就是这么试的

fn <- list.files(pn, '*.tif$', full.names = TRUE)
rn <- lapply(fn, raster)
bn <- brick(rn)

for (j in 1:ncell(bn)) {
  x <- bn[j]
  y <- which.max(x)
  x[y:length(x)] <- x[y]
}

现在,如果我不使用循环,这段代码就可以工作。错误可能是因为一些单元格有NA。每层有24个单元格,只有14个有数据。其余的被屏蔽。

nvbavucw

nvbavucw1#

对于处理栅格数据,我建议使用terra包。它是raster包的更新,速度更快,在大多数情况下更易于使用(你可以用install.packages('terra')安装它)。terra有一组apply函数,允许你在每一堆像素上应用函数。在下面的例子中,我使用一些虚拟数据创建了一个2x2像素的光栅,并使用terra::app函数执行您在问题中概述的过程:

# Create random data for 181 rasters.
x = seq(-0, 10, length.out=181)

# `dnorm` can be used to simulate a bell curve, like the NDVI data. 
vals = rep(dnorm(x, 5, 1), 4)

# I couldn't get the raster to reshape correctly so I am just taking the first
# 50 values so the data are a nice bell curve. 
arr <- array(vals, dim = c(2, 2, 50)) 

# Replace this with your data. From your code, you can just use:
# bn <- terra::rast(fn)
r <- terra::rast(arr)

# Define a custom function that operates on one stack of pixels at a time.
fill_max <- function(timeseries) {
  
  # Find the index with the max value
  idx = which.max(timeseries)
  
  # Set all values past the max to the max value
  timeseries[idx:length(timeseries)] <- timeseries[idx]
  
  return(timeseries)
}

# Apply the function to the raster.
out <- terra::app(r, fun=fill_max)

# Check that process worked. Take the timeseries of the first pixel. 
vals <- terra::values(out)[1,]
# Plot the timeseries. 
plot(1:length(vals), vals)

创建于2023年1月18日,使用reprex v2.0.2

h9a6wy2h

h9a6wy2h2#

如果希望曲线永远不会下降,可以使用terra::cummax
示例数据

library(terra)
r <- rast(ncol=10, nrow=10, nlyr=30)
set.seed(1)
values(r) <- runif(size(r))

溶液

x <- cummax(r)

图示为四个单元格

par(mfrow=c(2,2), mar=rep(2,4))
for (i in c(2,3,8,9)) {
  plot(unlist(r[i]))
  lines(unlist(x[i]), col="blue", lwd=2)
}

相关问题