我为Jean-Paul最受欢迎的答案写了一个Go包。它假设y值的类型为float64。
github.com/MicahParks/peakdetect
下面的示例使用了这个包,并基于上面提到的流行答案中的R示例。它在编译时没有任何依赖关系,试图保持较低的内存占用,并且在有新数据点进入时不重新处理过去的点。该项目有100%的测试覆盖率,主要来自上述R示例的输入和输出。但是,如果有人发现任何错误,请打开一个GitHub问题。
编辑:我对v0.0.5进行了性能改进,似乎快了10倍!它使用Welford的方法进行初始化,并使用类似的方法计算滞后期(滑动窗口)的平均值和总体标准偏差。特别感谢另一个帖子的回答:https://stackoverflow.com/a/14638138/14797322
下面是基于R例子的Golang例子:
package main
import (
"fmt"
"log"
"github.com/MicahParks/peakdetect"
)
// This example is the equivalent of the R example from the algorithm's author.
// https://stackoverflow.com/a/54507329/14797322
func main() {
data := []float64{1, 1, 1.1, 1, 0.9, 1, 1, 1.1, 1, 0.9, 1, 1.1, 1, 1, 0.9, 1, 1, 1.1, 1, 1, 1, 1, 1.1, 0.9, 1, 1.1, 1, 1, 0.9, 1, 1.1, 1, 1, 1.1, 1, 0.8, 0.9, 1, 1.2, 0.9, 1, 1, 1.1, 1.2, 1, 1.5, 1, 3, 2, 5, 3, 2, 1, 1, 1, 0.9, 1, 1, 3, 2.6, 4, 3, 3.2, 2, 1, 1, 0.8, 4, 4, 2, 2.5, 1, 1, 1}
// Algorithm configuration from example.
const (
lag = 30
threshold = 5
influence = 0
)
// Create then initialize the peak detector.
detector := peakdetect.NewPeakDetector()
err := detector.Initialize(influence, threshold, data[:lag]) // The length of the initial values is the lag.
if err != nil {
log.Fatalf("Failed to initialize peak detector.\nError: %s", err)
}
// Start processing new data points and determine what signal, if any they produce.
//
// This method, .Next(), is best for when data is being processed in a stream, but this simply iterates over a slice.
nextDataPoints := data[lag:]
for i, newPoint := range nextDataPoints {
signal := detector.Next(newPoint)
var signalType string
switch signal {
case peakdetect.SignalNegative:
signalType = "negative"
case peakdetect.SignalNeutral:
signalType = "neutral"
case peakdetect.SignalPositive:
signalType = "positive"
}
println(fmt.Sprintf("Data point at index %d has the signal: %s", i+lag, signalType))
}
// This method, .NextBatch(), is a helper function for processing many data points at once. It's returned slice
// should produce the same signal outputs as the loop above.
signals := detector.NextBatch(nextDataPoints)
println(fmt.Sprintf("1:1 ratio of batch inputs to signal outputs: %t", len(signals) == len(nextDataPoints)))
}