Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在R中查找时间序列峰值的开始和结束_R_Time Series - Fatal编程技术网

在R中查找时间序列峰值的开始和结束

在R中查找时间序列峰值的开始和结束,r,time-series,R,Time Series,我正在研究一年内有23次观测的NDVI时间序列数据。我能够检测到在14-19观测值之间出现的峰值。现在我想找到峰值的起点和终点。通过使用diff函数查找符号变化,我可以找到峰值的起点和终点。但在某些情况下,我可以找到终点,因为高峰的终点在明年。解决方法是重复观察23次后的数值,使其循环并找到终点 下面给出的示例将详细解释该问题 x = c(250.7943,292.2904,340.459,368.811,363.4534,330.2302,291.6527,275.2815,299.9305,

我正在研究一年内有23次观测的NDVI时间序列数据。我能够检测到在
14-19观测值之间出现的峰值。现在我想找到峰值的起点和终点。通过使用
diff函数
查找符号变化,我可以找到峰值的起点和终点。但在某些情况下,我可以找到终点,因为高峰的终点在明年。解决方法是重复观察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个值填充到向量的末尾,然后查找符号变化


有没有一种简单的方法可以实现这一点?

这只是为了创建一个可复制的示例:

y = data.frame(x = x, y = c(x[2:length(x)], NA))
y$diff <- y$y - y$x 
y=data.frame(x=x,y=c(x[2:长度(x)],NA))

y$diff使用洛基的方法,我能够部分解决我的问题

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
y=data.frame(x=x,y=c(x[2:长度(x)],x[1]))
y$diff另一种可能性:
(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



*例如,请参见

@loki感谢您的回复。。但是你弄错了。。。如果你看到上面的示例图像。。。有两个峰值,一个在4,一个在15。但我只对第二个峰值,即15感兴趣。因为这个起点是8点,终点是23点。在你们的解决方案中,开始是4,在我的例子中是第一个峰值,峰值是8,在我的例子中是第二个峰值的开始,结束是15,在我的例子中是第二个峰值。。但我从你的例子中得到了一些想法,可以用来解决我的问题…@Henrik,我尝试了你的代码,但它不起作用。。。问题出现在代码的第二部分
mins[排序(abs(mins-which.max(y)))[1:2]
<代码>分钟我已经用另一种方式做了。。。谢谢你的密码。。。我会检查一下并通知你。。。
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
# ...........
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
# 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)