LoginSignup
38
43

More than 5 years have passed since last update.

ピーク検出の方法

Last updated at Posted at 2019-02-15

先日こんなつぶやきを投稿した。

よく考えたら去年自分で書いてたわ。以下解説。

例えばこんなデータがあり、ピーク位置を検出したい。
Rplot1.png

ある点がピークだということは、ピークが極大の場合、その点の前後の点はピーク点の値より小さい(極小の場合はその逆)のはず。そこで、データx[1..n]に対して、d[i]=x[i]-x[i-1]を計算する。
Rplot2.png
このグラフで値が0になっている点がピークのはずだ。

次にq[i]=d[i]*d[i-1]を計算する。こんな感じになる。
Rplot3.png
値が負になっている点は、隣り合う2点の符号が異なっている点なので、この点の前後でdが0交差していることがわかる。そこで、値が負の点だけを拾ってくれば、それがピークになっている。

実際にはどんなピークを拾ってもよいわけではないので、ピークの値にしきい値を設けたり、大きいピークから順番に拾って、その周囲の一定範囲にあるピークは拾わないなどの細かい処理を行う。

コードはこんな感じ。

detect.peaks <- function(res,thres,pwidth,type="min") {
  len <- length(res)
  if (type == "min") {
    res[res>thres] <- thres
  } else {
    res[res<thres] <- thres
  }
  dif <- res[2:len]-res[1:len-1]
  ddif <- dif[2:(len-1)]*dif[1:(len-2)]
  ppos <- c()
  while (TRUE) {
    p <- which.min(ddif)
    if (ddif[p] == 0) break
    if (length(ppos)>0) {
      q <- abs(ppos-p)
      if (min(q) > pwidth) {
        ppos <- c(ppos,p)
      }
    } else {
      ppos <- c(ppos,p)
    }
    ddif[p] <- 0
  }
  ppos+1
}

これで検出してみる。

p <- detect.peaks(x,0.1,10,"max")

こんな感じになった。
Rplot4.png

追記

河原英紀先生からリプライをいただいた。

ピーク点は単調増加かつ単調減少であるという性質を使った方法です。こっちの方がエレガントかも。

38
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
43