# Dashboard Charts - 7 day rolling average

**URL:** <https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145>\
**Category:** General\
**Created:** [23 May 2020 16:28 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145 "2020-05-23T16:28:51Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [23 May 2020 16:28 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/1 "2020-05-23T16:28:51Z")

</div>

Anyone any idea how to create a 7 day rolling average from an array of objects, to plot in a node-RED chart?

The data arrives as an array of objects, comprising of a value, together with a epoch timestamp.  
There is just one object per day, and currently there is about 120 objects (4 months worth of data).

Abbreviated Example;

```auto
[{
	"x": 1590105600000,
	"y": 45
}, {
	"x": 1590105600000,
	"y": 53
}, {
	"x": 1589932800000,
	"y": 22
}, {
	"x": 1589932800000,
	"y": 30
}]

```

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [23 May 2020 16:38 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/2 "2020-05-23T16:38:37Z")

</div>

If you want just latest 7 days and the data is already sorted, you could (in a function node) use the array slice function followed by array reduce function.

Does that help? Need more?

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [23 May 2020 16:47 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/3 "2020-05-23T16:47:15Z")

</div>

> [@Steve-Mcl](#):
>
> If you want just latest 7 days

No, I want to plot the rolling 7 days average, starting from the earliest datapoint to the latest datapoint, so the chart data will absorb the anomalies.  
Example; the daily UK Coronavirus briefing, where accurate data is not received over a weekend, but the missing data is then added to Monday's data, resulting in a false representation. To avoid this, they plot the chart with a 7 day rolling average, which smoothes the chart.  
PS - It's not for plotting Coronavirus deaths!

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 May 2020 16:48 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/4 "2020-05-23T16:48:35Z")

</div>

the smooth node does an average over however many samples you say...

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [23 May 2020 16:55 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/5 "2020-05-23T16:55:09Z")

</div>

Yes, I've looked at that, but I haven't managed to handle an array of timestamped data using the node.  
If I strip out the data from the timestamp, and feed it as consecutive data points, I'm sure it would work, but then I've lost the timestamps, and therefore difficult to chart.

---

<div class="post-metadata">

**Author:** ![afelix](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/afelix/32/9743_2.png) [@afelix](https://discourse.nodered.org/u/afelix)\
**Post date:** [23 May 2020 18:09 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/6 "2020-05-23T18:09:17Z")

</div>

I’m not sure if I understand your needs correctly, but have you thought about supplying your data points to a function node with a reducer in it to calculate the rolling average?

> **[Array.prototype.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)**
>
> The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in single output value.

  
The reduce function gives access to current value, index in the array, as well as the full input array. Specifically the index and full input array sounds useful to me. That way you could build your output object but keep the timestamp (current object), while appending the calculated result to the reducer array (initial value/accumulator).

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 May 2020 18:43 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/7 "2020-05-23T18:43:19Z")

</div>

There is also a reduce mode within the join node that can be set to do whatever consolidation you want. The default example is average

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 May 2020 19:34 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/8 "2020-05-23T19:34:38Z")

</div>

I have assumed that for the first 6 samples what is wanted is the average of the samples so far.  
There are probably more compact ways of doing it but I imagine this is one of the most efficient techniques as keeps a rolling total rather than adding up seven values each time.

```auto
// Expects payload to be an array of objects {x: xvalue, y: yvalue}
// Performs a rolling average of y values over n samples and returns the result
// in payload.
const n = 7 // no of samples to average over
let total = 0
let count = 0 // number of samples accumulated
let answer = []
for (i = 0; i < msg.payload.length; i++) { 
    total += msg.payload[i].y
    if (i >= n) {
        total -= msg.payload[i-n].y
        count = n
    } else {
        count = i+1
    }
    answer[i] = {x: msg.payload[i].x, y: total/count}
}
msg.payload = answer
return msg;

```

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [23 May 2020 20:08 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/9 "2020-05-23T20:08:56Z")

</div>

The line  
`answer[i] = {x: msg.payload[i].x, y: total/count}`  
would have been better as  
`answer.push( {x: msg.payload[i].x, y: total/count} )`

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [23 May 2020 20:32 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/10 "2020-05-23T20:32:02Z")

</div>

Very clever @Colin, it's working fine on the live data, and it's also easy to switch the chart between original data and the 7 day rolling average by passing in the value of `n` via `msg.ra` with the data feed.

`const n = msg.ra || 7;`

Thank you 👍

Edit// @afelix, @dceejay I did try to use both suggestions, but found `reduce()` difficult to get right, and was just looking at the `join node` option when Colin's posted. - thanks both.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 May 2020 21:46 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/11 "2020-05-23T21:46:06Z")

</div>

looking at your original data - why do you have duplicate x values ?

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [23 May 2020 22:05 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/12 "2020-05-23T22:05:40Z")

</div>

Because it's not the real data, it is just an example to show the format of the data, so it would be clear how the array is structured.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 May 2020 22:07 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/13 "2020-05-23T22:07:40Z")

</div>

OK, NP. Just checking you weren't getting weird feed

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [8 June 2020 21:32 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/16 "2020-06-08T21:32:38Z")

</div>

A post was split to a new topic: [Remove duplicate entries from a array](https://discourse.nodered.org/t/remove-duplicate-entries-from-a-array/28013)

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [8 June 2020 21:34 UTC](https://discourse.nodered.org/t/dashboard-charts-7-day-rolling-average/27145/17 "2020-06-08T21:34:41Z")

</div>


