我正在处理NDVI Time-Series
一年内23 observations
的数据。我能够检测14 - 19 observation
之间出现的峰值。现在我想找到start and end of the Peak
。通过使用diff function
查找符号更改,我可以找到峰值的开始和结束。但在某些情况下,我注意到能够找到结束,因为峰值的结束是在明年。解决方案是在23次观察后重复这些值,使其循环并找到结束。
下面给出的例子将详细解释问题
x = c(250.7943,292.2904,340.459,368.811,363.4534,330.2302,291.6527,275.2815,299.9305,367.0331,461.2618,559.0772,639.6197,691.723,713.9833,709.5409,680.4415,626.1153,547.0395,450.4623,353.0839,277.257,241.597)
我正在寻找从山顶向两个方向的标志变化,并且能够在8点观察时找到峰值的开始但是当我从峰值开始寻找结束时我直到23才能找到任何变化。在这种情况下,我应该在23处结束峰值。如表所示,我在Excel中手动重复这些值以获得符号更改。
如何在R ???
中完成此操作一个解决方案可能是设置一个条件来检查是否找不到符号更改,直到23次观察,然后所有23个值将在向量的末尾填充,然后查找符号更改。
有没有一种简单的方法可以实现这个目标?
答案 0 :(得分:2)
另一种可能性:
(1)使用前导和滞后Inf
填充您的值,以在时间序列的开头和结尾创建虚拟局部最小值*。 (2)查找所有最小值(包括假人)的索引。 (3)找到最大值旁边的两个最小值的索引。
# pad values with Inf and get indexes of all local minima
i.mins <- which(diff(sign(diff(c(Inf, x, Inf)))) == 2)
# index of max value
i.mx <- which.max(x)
# combine indexes of local minima and the max
i <- sort(c(i.mins, i.mx))
# select the two minima on either side of the max
ix <- i[which(i == i.mx) + c(-1, 1)]
ix
# [1] 8 23
plot(x, type = "b")
points(x = c(ix[1], i.mx, ix[2]),
y = c(x[ix[1]], max(y), x[ix[2]]),
col = c("blue", "red", "blue"), pch = 19, cex = 2)
答案 1 :(得分:1)
这只是为了创建一个可重现的例子:
y = data.frame(x = x, y = c(x[2:length(x)], NA))
y$diff <- y$y - y$x
然后我们开始生成一个新列:
y$startEndPeak <- NA
然后我们遍历data.frame,保存所有差异记录。因此,我们通过比较所有差异与之前的对应部分来识别起点/终点和峰值:
for(i in 2:(nrow(y) - 1)){
thisDif <- y$diff[i]
prevDif <- y$diff[i-1]
if (thisDif < 0 && prevDif > 0){
y$startEndPeak[i] <- "start/end"
}
if (thisDif > 0 && prevDif < 0){
y$startEndPeak[i] <- "peak"
}
}
y
# x y diff startEndPeak
# 1 250.7943 292.2904 41.4961 <NA>
# 2 292.2904 340.4590 48.1686 <NA>
# 3 340.4590 368.8110 28.3520 <NA>
# 4 368.8110 363.4534 -5.3576 start/end
# 5 363.4534 330.2302 -33.2232 <NA>
# 6 330.2302 291.6527 -38.5775 <NA>
# 7 291.6527 275.2815 -16.3712 <NA>
# 8 275.2815 299.9305 24.6490 peak
# 9 299.9305 367.0331 67.1026 <NA>
# 10 367.0331 461.2618 94.2287 <NA>
# 11 461.2618 559.0772 97.8154 <NA>
# 12 559.0772 639.6197 80.5425 <NA>
# 13 639.6197 691.7230 52.1033 <NA>
# 14 691.7230 713.9833 22.2603 <NA>
# 15 713.9833 709.5409 -4.4424 start/end
# 16 709.5409 680.4415 -29.0994 <NA>
# 17 680.4415 626.1153 -54.3262 <NA>
# 18 626.1153 547.0395 -79.0758 <NA>
# 19 547.0395 450.4623 -96.5772 <NA>
# 20 450.4623 353.0839 -97.3784 <NA>
# 21 353.0839 277.2570 -75.8269 <NA>
# 22 277.2570 241.5970 -35.6600 <NA>
# 23 241.5970 NA NA <NA>
然后我们使用向量来放置起点和终点
y$startEndPeak[which(y$startEndPeak == "start/end")] <- c("start", "end")
y
# x y diff startEndPeak
# ...........
# 3 340.4590 368.8110 28.3520 <NA>
# 4 368.8110 363.4534 -5.3576 start
# ...........
# 8 275.2815 299.9305 24.6490 peak
# ...........
# 15 713.9833 709.5409 -4.4424 end
# ...........
答案 2 :(得分:1)
Usimg Loki的方法我能够部分解决我的问题......
y = data.frame(x = x, y = c(x[2:length(x)], x[1]))
y$diff <- y$y - y$x
y$startEndPeak <- NA
for(i in 2:(nrow(y))){
thisDif <- y$diff[i]
prevDif <- y$diff[i-1]
if (thisDif < 0 && prevDif > 0){
y$startEndPeak[i] <- "peak"
}
if (thisDif > 0 && prevDif < 0){
y$startEndPeak[i-1] <- "end"
y$startEndPeak[i] <- "start"
}
}
y
# x y diff startEndPeak
# 250.7943 292.2904 41.4961 <NA>
# 292.2904 340.4590 48.1686 <NA>
# 340.4590 368.8110 28.3520 <NA>
# 368.8110 363.4534 -5.3576 peak
# 363.4534 330.2302 -33.2232 <NA>
# 330.2302 291.6527 -38.5775 <NA>
# 291.6527 275.2815 -16.3712 end
# 275.2815 299.9305 24.6490 start
# 299.9305 367.0331 67.1026 <NA>
# 367.0331 461.2618 94.2287 <NA>
# 461.2618 559.0772 97.8154 <NA>
# 559.0772 639.6197 80.5425 <NA>
# 639.6197 691.7230 52.1033 <NA>
# 691.7230 713.9833 22.2603 <NA>
# 713.9833 709.5409 -4.4424 peak
# 709.5409 680.4415 -29.0994 <NA>
# 680.4415 626.1153 -54.3262 <NA>
# 626.1153 547.0395 -79.0758 <NA>
# 547.0395 450.4623 -96.5772 <NA>
# 450.4623 353.0839 -97.3784 <NA>
# 353.0839 277.2570 -75.8269 <NA>
# 277.2570 241.5970 -35.6600 end
# 241.5970 250.7943 9.1973 start