[英]Stack rasters and calculate each pixel's max value then keep that value for rest of the layers in R
I have 181 daily ndvi rasters stacked.我每天堆叠 181 个 ndvi 光栅。 I want to find peak for each pixel and then assign peak value to the rest. Original Data Curve:我想为每个像素找到峰值,然后将峰值分配给 rest。原始数据曲线:
This is what I want:这就是我要的:
This result is for single pixel.此结果适用于单个像素。 I've done it in excel but want to create a code in R for ease.我已经在 excel 中完成了,但为了方便起见,我想在 R 中创建一个代码。 Now every pixel reaches peak at different date (so different Layer in stack).现在每个像素在不同的日期达到峰值(因此堆栈中的不同层)。
This is what i tried这是我试过的
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]
}
Now this code works if I use it without loop.现在,如果我在没有循环的情况下使用它,这段代码就可以工作了。 Error is probably because some cells have NA's.错误可能是因为某些单元格有 NA。 Each layer has 24 cells and only 14 have data.每层有 24 个单元,只有 14 个有数据。 Rest are masked. Rest 被屏蔽了。
For processing raster data, I would recommend using the terra
package. It is an update to the raster
package that is faster and in most cases easier to use (you can install it with install.packages('terra')
).对于处理栅格数据,我建议使用terra
package。它是对raster
package 的更新,速度更快,在大多数情况下更易于使用(您可以使用install.packages('terra')
安装)。 terra
has a set of apply
functions that allow you to apply functions over each stack of pixels. terra
有一组apply
函数,允许您在每个像素堆栈上应用函数。 In the example below, I create a 2x2 pixel raster with some dummy data, and use the terra::app
function to carry out the process you outline in your question:在下面的示例中,我创建了一个带有一些虚拟数据的 2x2 像素栅格,并使用terra::app
function 执行您在问题中概述的过程:
# 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)
Created on 2023-01-18 with reprex v2.0.2创建于 2023-01-18,使用reprex v2.0.2
If you wanted the curve to never go down, you could use terra::cummax
如果您希望曲线永远不会下降 go,您可以使用terra::cummax
Example data示例数据
library(terra)
r <- rast(ncol=10, nrow=10, nlyr=30)
set.seed(1)
values(r) <- runif(size(r))
Solution解决方案
x <- cummax(r)
Illustrated for four cells图示为四个电池
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)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.