我有一个640个值的数组,其中包含画一条线所需的y值。
我需要确定每个三个峰的顶部的阵列位置。
我在这里查看了与局部最大值/局部最小值有关的类似问题,但是运行我发现的代码会遇到一些小的问题。我只需要三个非常不同的峰。
我正在尝试使用Javascript执行此操作。来自数组的数据如下:
126,126,126,126,126,126,126,126,126,126,126,126,126,126,124,123,122,122,120,119,119,118,118,118,119,119,119,120,121,121,122,124,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,124,125,124,125,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,123,124,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,122,123,122,123,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,119,119,119,119,116,115,114,113,113,113,113,113,115,117,118,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,108,107,106,118,108,108,103,103,103,103,103,103,104,105,107,108,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109
我在数组上运行了这段代码:
function pickPeaks(arr){
return arr.reduce( (res, val, i, self) => {
if(
// a peak when the value is greater than the previous and greater than the next
val > self[i - 1] && val > self[i + 1]
||
// a plateau when the value is greater than the previuos and equal to the next and from there the next different value is less
val > self[i - 1] && val === self[i + 1] && self.slice(i).find( item => item !== val ) < val
){
res.pos.push(i);
res.peaks.push(val);
}
return res;
}, { pos:[],peaks:[] } );
}
console.log(pickPeaks(first_black_array))
并输出以下内容:
peaks: (9) [362, 356, 356, 357, 358, 358, 367, 374, 377]
pos: (9) [21, 67, 69, 112, 179, 181, 313, 608, 612]
我希望结果是这样的:
pos: [24, 316, 616]
(每个峰的顶部)
非常感谢
答案 0 :(得分:2)
要扩大我的评论,类似
function detectPeaks(data, windowWidth, threshold) {
const peaks = [];
for (let i = 0; i < data.length; i++) {
const start = Math.max(0, i - windowWidth);
const end = Math.min(data.length, i + windowWidth);
let deltaAcc = 0;
for (let a = start; a < end; a++) {
deltaAcc += Math.abs(data[a - 1] - data[a]);
}
if (deltaAcc > threshold) {
peaks.push(i);
}
}
return peaks;
}
找到“峰值”(或者说是价值变化比其他地方变化多的区域)很好。
您可以在https://codepen.io/akx/pen/QowEQq上找到一个交互式示例,在这里您还可以调整窗口宽度和阈值。
答案 1 :(得分:0)
与先前的值相比,您可以查找较小的值,并通过更新最后一个最小值的索引来查找,如果值增加,则按新的最小值。
实际上,根据问题,此方法返回的索引最小值为608,否则不应为最小值。也许您需要过滤的最小值最小值太小。
var data = [126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 124, 123, 122, 122, 120, 119, 119, 118, 118, 118, 119, 119, 119, 120, 121, 121, 122, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 124, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 116, 115, 114, 113, 113, 113, 113, 113, 115, 117, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 108, 107, 106, 118, 108, 108, 103, 103, 103, 103, 103, 103, 104, 105, 107, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109],
push = true,
last = 0,
result = data.reduce((r, v, i, a) => {
if (a[r[last]] === v) { // take latest index of series
r[last] = i;
return r;
}
if (a[i - 1] < v) { // look for new series
push = true;
return r;
}
if (a[i - 1] > v) {
if (push && a[i - 1] > a[r[last]]) { // prevent continuing minima
last = r.push(i) - 1;
push = false;
} else {
r[last] = i;
}
}
return r;
}, []);
console.log('values ', result.map(i => data[i].toString().padStart(3)).join(' '));
console.log('indices', result.map(v => v.toString().padStart(3)).join(' '));
答案 2 :(得分:0)
此功能将遍历您的数据并确定数据中最大的过渡。然后它将对它们进行协调,以便在获取n
条记录时不会向您输出相同的峰。
function getPeaks(data, n = 3, peakList = []) {
return data.reduce((a, v, i, _a,
end_index = _a.length - 1,
change = v - _a[i - 1] || 0,
mate = i + Math.sign(change),
_ = (change) && a.peaks.push({change,i,mate})
) => (i === end_index) ?
(a.peaks.forEach(_ =>
(!peakList.includes(_.i) && (mate = a.peaks.find(__ =>
__.i === _.mate))) && (a.samePeak.push({
highpoint: data[_.i] > data[mate.i] ? _.i : mate.i,
steepness: mate.change > _.change ? mate.change : _.change
})),
peakList.push(_.i, mate.i)),
a.samePeak.sort((_, __) =>
__.steepness - _.steepness)
.map(_ => _.highpoint)
.slice(0, n)) : a, {
peaks: [],
samePeak: []
})
}
let data = [126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 124, 123, 122, 122, 120, 119, 119, 118, 118, 118, 119, 119, 119, 120, 121, 121, 122, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 124, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 124, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, 123, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 119, 119, 119, 119, 116, 115, 114, 113, 113, 113, 113, 113, 115, 117, 118, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 108, 107, 106, 118, 108, 108, 103, 103, 103, 103, 103, 103, 104, 105, 107, 108, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109]
function getPeaks(data, n = 3, peakList = []) {
return data.reduce((a, v, i, _a,
end_index = _a.length - 1,
change = v - _a[i - 1] || 0,
mate = i + Math.sign(change),
_ = (change) && a.peaks.push({
change,
i,
mate
})
) => (i === end_index) ?
(a.peaks.forEach(_ =>
(!peakList.includes(_.i) && (mate = a.peaks.find(__ =>
__.i === _.mate))) && (a.samePeak.push({
highpoint: data[_.i] > data[mate.i] ? _.i : mate.i,
steepness: mate.change > _.change ? mate.change : _.change
})),
peakList.push(_.i, mate.i)),
a.samePeak.sort((_, __) =>
__.steepness - _.steepness)
.map(_ => _.highpoint)
.slice(0, n)) : a, {
peaks: [],
samePeak: []
})
}
//getpeaks(data, number of peaks to get)
console.log( getPeaks(data, 3) );
诚然,当我经历-时,它变得有些模糊::)这是一个更清晰的版本:
function getPeaks(data, n = 3, peakList = [] ) {
return data.reduce( ( a, v, i, _a, end_index = _a.length - 1 ) => {
change = v - _a[ i - 1 ] || 0,
mate = i + Math.sign( change ),
payload = {
change,
i,
mate
};
if ( change ) a.peaks.push( payload );
return ( i === end_index ) ? ( a.peaks.forEach( _ => {
if ( peakList.includes( _.i ) ) return;
if ( mate = a.peaks.find( __ => __.i === _.mate ) ) {
a.samePeak.push( {
highpoint: data[ _.i ] > data[ mate.i ] ? _.i : mate.i,
steepness: mate.change > _.change ? mate.change : _.change
} )
peakList.push( _.i, mate.i );
}
} ), a ) : a;
}, {
peaks: [],
samePeak: []
} ).samePeak.sort( ( _, __ ) => __.steepness - _.steepness )
.map(({highpoint})=>highpoint)
.slice( 0, n );
}
function getPeaks(data, n = 3, peakList = [] ) {
return data.reduce( ( a, v, i, _a, end_index = _a.length - 1 ) => {
change = v - _a[ i - 1 ] || 0,
mate = i + Math.sign( change ),
payload = {
change,
i,
mate
};
if ( change ) a.peaks.push( payload );
return ( i === end_index ) ? ( a.peaks.forEach( _ => {
if ( peakList.includes( _.i ) ) return;
if ( mate = a.peaks.find( __ => __.i === _.mate ) ) {
a.samePeak.push( {
highpoint: data[ _.i ] > data[ mate.i ] ? _.i : mate.i,
steepness: mate.change > _.change ? mate.change : _.change
} )
peakList.push( _.i, mate.i );
}
} ), a ) : a;
}, {
peaks: [],
samePeak: []
} ).samePeak.sort( ( _, __ ) => __.steepness - _.steepness )
.map(({highpoint})=>highpoint)
.slice( 0, n );
}
console.log( getPeaks(data, 3) );