16
\$\begingroup\$

Note: This is #3 in a series of challenges. For the previous challenge, click here.

Moving Average of a List

The moving average of a list is a calculation resulting in a new, smoothed out list, created by averaging small overlapping sublists of the original.

When creating a moving average, we first generate the list of overlapping sublists using a certain 'window size', shifting this window to the right once each time.

For example, given the list [8, 4, 6, 2, 2, 4] and the window size 3, the sublists would be:

[8,  4,  6,  2,  2,  4]          Sublists:
(         )                  <-  [8, 4, 6]
    (         )              <-  [4, 6, 2]
        (         )          <-  [6, 2, 2]
            (         )      <-  [2, 2, 4]

We then calculate the mean average of each sublist to obtain the result: [6.0, 4.0, 3.3, 2.7] (each value rounded to one decimal place).


The Challenge

Your task is to write a program or function which, given a list L, and an integer 1 ≤ n ≤ length(L), calculate the moving average for L using the window size n.

Rules:

  • Your program may use integer division or float division. In the case of float division, small inaccuracies due to the data type's limitations are permitted, as long as the value is otherwise correct.
  • You may submit a full program, or a function (but not a snippet).
  • You may assume that the list will only contain positive integers.
  • Standard loopholes are forbidden.
  • This is , so the shortest answer (in bytes) wins!

Test Cases

Note that, for ease of readability, all values are rounded to one decimal place.

n=5, [1, 2, 3, 4, 5, 6, 7, 8]      ->      [3, 4, 5, 6]
n=3, [100, 502, 350, 223, 195]     ->      [317.3, 358.3, 256]
n=1, [10, 10, 10]                  ->      [10, 10, 10]
n=3, [10, 20, 30]                  ->      [20]
n=2, [90, 40, 45, 100, 101]        ->      [65, 42.5, 72.5, 100.5]
\$\endgroup\$
  • \$\begingroup\$ Do we have to round float values, or can we leave them as they are? \$\endgroup\$ – caird coinheringaahing Nov 5 '17 at 16:01
  • 3
    \$\begingroup\$ @cairdcoinheringaahing Note that, for ease of readability, all values are rounded to one decimal place. In my opinion, you can definitely leave them as they are (at least that's what I understand). \$\endgroup\$ – Mr. Xcoder Nov 5 '17 at 16:01
  • \$\begingroup\$ @cairdcoinheringaahing I've been quite liberal with I/O: integer or float values are fine, you may round if you want but don't have to, and floating point errors are allowed \$\endgroup\$ – FlipTack Nov 5 '17 at 16:03
  • \$\begingroup\$ Is it okay to return fractions instead of floating point numbers? \$\endgroup\$ – JungHwan Min Nov 5 '17 at 16:23
  • \$\begingroup\$ @JungHwanMin If for accuracy, your language will store values as fractions rather than floats, it's fine to print them as accurate fractions in their simplest forms. \$\endgroup\$ – FlipTack Nov 5 '17 at 16:26

32 Answers 32

7
\$\begingroup\$

Jelly, 3 bytes

ṡÆm

Try it online!

Pretty simple thanks to

How it works

ṡÆm - Main dyadic link. Arguments: l (list) and n (integer)
ṡ   - Split l into sublists of length n
 Æm - Mean of each
\$\endgroup\$
7
\$\begingroup\$

Wolfram Language (Mathematica), 13 bytes

Mathematica has a built-in for everything

MovingAverage

Try it online!

Takes a list and then a radius...

\$\endgroup\$
  • 6
    \$\begingroup\$ MovingAverage ಠ_____ಠ I refuse to believe this \$\endgroup\$ – Mr. Xcoder Nov 5 '17 at 16:23
  • \$\begingroup\$ @cairdcoinheringaahing Takes the numerical value. MovingAverage returns a set of fractions. Now that it's been allowed by the OP, MovingAverage should suffice indeed. \$\endgroup\$ – Mr. Xcoder Nov 5 '17 at 16:33
7
\$\begingroup\$

Haskell, 47 bytes

n!a|length a<n=[]|_:t<-a=div(sum$take n a)n:n!t

Try it online!

Saved two bytes thanks to xnor!

\$\endgroup\$
  • 1
    \$\begingroup\$ tail a can be extracted in the guard. \$\endgroup\$ – xnor Nov 5 '17 at 17:30
  • \$\begingroup\$ Gah, I knew I was missing something like that. Thank you! \$\endgroup\$ – Lynn Nov 5 '17 at 20:02
7
\$\begingroup\$

Dyalog APL, 4 bytes

1 byte saved thanks to @Graham

2 bytes saved thanks to @jimmy23013

Did I mention APL is not a golfing language?

⊢+/÷

with n on the right, or

+/÷⊣

with L on the right.

Try it online!

How?

÷ - divide L by n

⊢+/ - reduce + on windows of n

\$\endgroup\$
  • \$\begingroup\$ Why not divide L by n before the reduction. Saves a byte \$\endgroup\$ – Graham Nov 5 '17 at 16:49
  • \$\begingroup\$ ⊢+/÷ \$\endgroup\$ – jimmy23013 Nov 6 '17 at 9:13
  • \$\begingroup\$ Or +/÷⊣ \$\endgroup\$ – jimmy23013 Nov 6 '17 at 9:16
  • \$\begingroup\$ @jimmy23013 thanks alot! I tried that one earlier, but must've typed the arguments wrong cos it didn't work. \$\endgroup\$ – Uriel Nov 6 '17 at 10:51
6
\$\begingroup\$

Python, 48 bytes

f=lambda n,l:l[n-1:]and[sum(l[:n])/n]+f(n,l[1:])

Try it online!

A recursive function. Shorter than the program (50 bytes)

n,l=input()
while l[-n]:print sum(l[:n])/n;l=l[1:]

Try it online!

This saves 2 bytes by terminating with error on the while condition.

\$\endgroup\$
4
\$\begingroup\$

Enlist, 3 bytes

ṡÆm

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Polyglot with Jelly :P \$\endgroup\$ – caird coinheringaahing Nov 5 '17 at 16:38
  • \$\begingroup\$ @cairdcoinheringaahing I only just noticed your Jelly answer too lol :P \$\endgroup\$ – Mr. Xcoder Nov 5 '17 at 16:38
4
\$\begingroup\$

Perl 6, 33 bytes

{@^a.rotor($^b=>1-$b)».sum X/$b}

Test it

Expanded:

{  # bare block with placeholder parameters 「@a」, 「$b」

  @^a                # declare and use first param

  .rotor(            # split it into chunks
    $^b              # declare and use second param
    =>               # pair it with
    1 - $b           # one less than that, negated

  )».sum             # sum each of the sub lists

  X/                 # cross that using &infix:«/»

  $b                 # with the second param
}
\$\endgroup\$
4
\$\begingroup\$

C,  86   84  83 bytes

i,j,s;f(a,l,n)int*a;{for(i=-1;i+++n<l;s=!printf("%d ",s/n))for(j=n;j--;)s+=a[i+j];}

Try it online!

Unrolled:

i, j, s;
f(a, l, n)int*a;
{
    for(i=-1; i+++n<l; s=!printf("%d ", s/n))
        for(j=n; j--;)
            s += a[i+j];
}
\$\endgroup\$
4
\$\begingroup\$

J, 7 5 bytes

]+/\%

Try it online!

Takes n as the right argument and the list as the left. Credit to Uriel's solution for the idea of doing only the summation in the infix.

Explanation

]+/\%
    %  Divide list by n
]+/\   Sum on overlapping intervals of size n

Previous solution (7 bytes)

(+/%#)\
      \  Apply to overlapping intervals of size n
(+/%#)   Mean
 +/        Sum
   %       Divided by
    #      Length
\$\endgroup\$
4
\$\begingroup\$

Ohm v2, 3 bytes

ÇÆm

Try it online!

Explanation:

ÇÆm  Main wire, arguments l (list) and n (integer)

Ç    All consecutive sublists of l with length n
 Æm  Arithmetic mean of each sublist
\$\endgroup\$
3
\$\begingroup\$

Pyth, 5 bytes

.O.:F

Try it here!

How this works

.O.:F  - Full program.

    F  - Reduce the input (nested list) with...
  .:   - ... Sublists.
.O     - Average of each.
\$\endgroup\$
3
\$\begingroup\$

Octave, 33 31 bytes

@(x,n)conv(x,~~(1:n)/n,'valid')

Try it online!

Explanation

Convolution (conv) is essentially a moving weighted sum. If the weights are chosen as [1/n, ..., 1/n] (obtained as ~~(1:n)/n) the result is a moving average, of which only the 'valid' part is kept.

\$\endgroup\$
2
\$\begingroup\$

R, 72 bytes

function(l,n)(k=sapply(0:sum(l|1),function(x)mean(l[x+1:n])))[!is.na(k)]

Try it online!

Computes the mean of all the size n windows; when the window goes past the edge of l, the results are NA so we filter them out.

R + zoo package, 13 bytes

zoo::rollmean

The zoo package (S3 infrastructure for Regular and Irregular Time Series) has a lot of handy functions. You may try it here (R-fiddle).

\$\endgroup\$
2
\$\begingroup\$

Japt v2.0a0, 7 bytes

ãV ®x÷V

Try it


Explanation

Implicit input of array U and integer V.

ãV

Get subsections of U with length V

®

Map over the subsections.

÷V

Divide each element by V.

x

Sum all elements.

\$\endgroup\$
1
\$\begingroup\$

Python 3, 61 bytes

lambda l,n:[sum(e)/n for e in zip(*[l[i:]for i in range(n)])]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 55 bytes

lambda n,A:[sum(A[j:n+j])/n for j in range(-n-~len(A))]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 5 bytes

ŒsùÅA

Explanation:

Π    All substrings
 sù   Keep those only where the length is equal to <the second input>
   ÅA Arithmetic mean of each element in the resulting array.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Mathematica, 21 bytes

Mean/@##~Partition~1&

Try it online!

-3 bytes JungHwan Min

\$\endgroup\$
  • \$\begingroup\$ -3 bytes: N[Mean/@##~Partition~1]& \$\endgroup\$ – JungHwan Min Nov 5 '17 at 16:24
1
\$\begingroup\$

Proton, 46 bytes

n=>l=>[sum(l[h to h+n])/n for h:0..len(l)-n+1]

Try it online!

Note that this takes input via currying functions syntax, and returns a list of fractions.

\$\endgroup\$
1
\$\begingroup\$

CJam, 14 12 bytes

-2 bytes thanks to @aditsu

{_@ew::+\f/}
\$\endgroup\$
0
\$\begingroup\$

Jq 1.5, 61 bytes

def f(N;L):[L|range(0;1+length-N)as$i|.[$i:$i+N]|add/length];

Expanded

def f(N;L):
  [   L
    | range(0;1+length-N) as $i        # generate
    | .[$i:$i+N]                       # sublists
    | add/length                       # compute mean
  ];

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 53 bytes

(l,n)=>l.map(e=>(s+=e-=a[i-n]||0)/n,s=i=0).slice(n-1)
\$\endgroup\$
0
\$\begingroup\$

PHP, 94 bytes

function f($l,$n){while($i<=count($l)-$n)$r[]=array_sum(array_slice($l,$i++,$n))/$n;return$r;}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Clojure, 48 bytes

(fn[n a](map #(/(apply + %)n)(partition n 1 a)))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Stacked, 22 bytes

[infixes[:sum\#'/]map]

Try it online!

Explanation

infixes generates all the windows of the given length. Then, we map our own average function over each infix.

\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 77 bytes

(defun f(x y)(if(>=(length x)y)(cons(/(apply'+(subseq x 0 y))y)(f(cdr x)y))))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

K (oK), 13 11 bytes

Solution:

{+/+x':y%x}

Try it online!

Examples:

{+/+x':y%x}[3;8 4 6 2 2 4]
6 4 3.3333 2.6667
{+/+x':y%x}[5;1 2 3 4 5 6 7 8]
3 4 5 6

Explanation:

oK has a built-in for creating a sliding window, then sum up resulting arrays and divide by sliding window size to get mean:

{+/+x':y%x} / the solution
{         } / lambda function taking x and y as implicit parameters
       y%x  / y (list) by x (sliding array size)
    x':     / sliding window of size x over list y
   +        / flip array (rotate by 90 degrees)
 +/         / sum up array
\$\endgroup\$
  • \$\begingroup\$ Looks like you don't need the flip array +, and if K has commute like APL you can move x%[commute] to left and drop the parens \$\endgroup\$ – Uriel Nov 6 '17 at 15:10
  • \$\begingroup\$ The flip is needed to ensure the sum is across rather than down each list, and fairly sure there's no commute operator, at least nothing to suggest it in the manual. Cheers though! \$\endgroup\$ – streetster Nov 6 '17 at 16:23
0
\$\begingroup\$

DataWeave, 50 bytes

fun s(l,w)=0 to(sizeOf(l)-w)map avg(l[$ to $+w-1])
%dw 2.0
output application/json

fun sma(list: Array<Number>, window: Number) =
  0 to (sizeOf(list) - window)  // generate starting indices of sublists
  map list[$ to $ + window - 1] // generate sublists
  map avg($)                    // calculate averages

---
sma([90, 40, 45, 100, 101], 2)
\$\endgroup\$
0
\$\begingroup\$

Funky, 67 66 bytes

Saved a byte with curry syntax.

n=>t=>{k={}fori=0i<=(#t)-n i++k[i]=(forj=c=0c<n c++j+=t[i+c])/n k}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Java 8, 111 bytes

a->n->{int l=a.length-n+1,i=0,j;float[]r=new float[l];for(;i<l;r[i++]/=n)for(j=i;j<i+n;r[i]+=a[j++]);return r;}

Explanation:

Try it here.

a->n->{                 // Method with array and int parameters and float-array return-type
  int l=a.length-n+1,   //  New length of the return-array
      i=0,j;            //  Index-integers
  float[]r=new float[l];//  Return-array
  for(;i<l;             //  Loop (1) from 0 to `l` (exclusive)
      r[i++]/=n)        //    After every iteration, divide the current item by input `n`
    for(j=i;j<i+n;      //   Inner loop (2) from `i` to `i+n` (exclusive)
      r[i]+=a[j++]      //    Sum the result at index `i` with the items of the input-array
    );                  //   End of inner loop (2)
                        //  End of loop (1) (implicit / single-line body)
  return r;             //  Return the resulting float-array
}                       // End of method
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.