Reputation: 11
Assume a Json array of numbers:
[ 1, 4, 6, 9, 8, 10, 5, 2]
I want to compute a 3 day moving average. The resulting array is computed by averaging the previous 3 entries.
So the first 3 entries don't care, the 4th is (1+4+6)/3
, the 5th is (4+6+9)/3
and so on.
Conceptually, this is what I'm trying to do:
echo '[ 1, 4, 6, ... ]' | jq 'map(average(select(prev 3 array entries)))'
Upvotes: 1
Views: 2044
Reputation: 14705
Here is a jq filter which uses a recursive function to compute the moving average of every n elements.
def avg(n):
if length < n then empty # base case
else ( .[0:n] | add/n ) # average of first n elements
, ( .[1:] | avg(n) ) # recursive call
end
;
avg(3)
Upvotes: 1
Reputation: 134521
You can use a filter like this:
def rolling_average(size): . as $items |
[ range(0;length-size)
| $items[.:.+size]
| add/size
]
;
rolling_average(3)
The idea is to generate the range of indices to get the averages of, then take the average of those items.
Upvotes: 0
Reputation: 11
This question inspired me to learn jq, thanks!
my solution is
'. as $val | to_entries | map((.value + $val[.key-1] + $val[.key-2])/3) | .[2:]'
First step, save whole array to variable $val
second step transforms array into array of object with keys (try it!, it transforms your example array into
[
{
"key": 0,
"value": 1
},
{
"key": 1,
"value": 4
},
{
"key": 2,
"value": 6
},
{
"key": 3,
"value": 9
},
{
"key": 4,
"value": 8
},
{
"key": 5,
"value": 10
},
{
"key": 6,
"value": 5
},
{
"key": 7,
"value": 2
}
]
)
third step gets value from each point and adds value of two previous steps
last step is optional, it throws out values "you don't care about"
Upvotes: 1