Issue
Would like to convert my current Angular reduce
function below to calculate a moving average based on a period of every ~2-3 items. Is this possible to do w/ a standard Angular Reduce function?
This is what I currently have to compute a basic average, but would like to convert it to a moving average w/ a settable period if possible, but not sure how/if it's possible to do w/ a standard Angular JS Reduce function.
const data = [
{ val: 20 },
{ val: 15 },
{ val: 10 },
{ val: 12 },
{ val: 15 },
{ val: 09 },
{ val: 14 },
{ val: 17 },
{ val: 11 },
{ val: 15 }
]
var avg = data.reduce((accum, curVal) => accum + curVal.val, 0) / data.length;
console.log("avg= " + avg);
Solution
If I've understood the question correctly you want an array with a set of averages based on a window that moves one entry at a time across the data. Here's an example using a for loop, please see the comments for how this works:
const data = [{ val: 20 }, { val: 15 }, { val: 10 }, { val: 12 }, { val: 15 }, { val: 9 }, { val: 14 }, { val: 17 }, { val: 11 }, { val: 15 }];
const get_moving_averages = (data, window_size = 3) => {
const sums = [];
for(let i = 0; i < data.length; i++) {
if(i < window_size) {
// add everything to the first slot for the first items up to window size
sums[0] = (sums[0] ?? 0) + data[i];
} else {
// calculate value by taking the previous value, adding the new data
// and taking off value that shouldn't be included in this sum from the previous sum
sums[i + 1 - window_size] = sums[i - window_size] + data[i] - data[i - window_size];
}
}
return sums.map((sum) => sum / window_size);
};
console.log(get_moving_averages(data.map(({val}) => val)));
Same idea but with a reduce function:
const data = [{ val: 20 }, { val: 15 }, { val: 10 }, { val: 12 }, { val: 15 }, { val: 9 }, { val: 14 }, { val: 17 }, { val: 11 }, { val: 15 }];
const get_moving_averages = (data, window_size = 3) =>
data.reduce((acc, val, i, all) => {
const first_few = i < window_size;
const sum_index = first_few ? 0 : i + 1 - window_size;
acc[sum_index] = (acc[sum_index] ?? 0) + val;
if(!first_few)
acc[sum_index] += acc[sum_index - 1] - all[i - window_size];
return acc;
}, [])
.map( (sum) => sum / window_size );
console.log(get_moving_averages(data.map(({val}) => val)));
Answered By - Ben Stephens
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.