Skip to content

Instantly share code, notes, and snippets.

@eldritchideen
Created January 31, 2015 00:33
Show Gist options
  • Save eldritchideen/b8edcea93ced80b03f53 to your computer and use it in GitHub Desktop.
Save eldritchideen/b8edcea93ced80b03f53 to your computer and use it in GitHub Desktop.
Moving Average in Clojure
(defn average [coll]
(/ (reduce + coll)
(count coll)))
(defn ma [period coll]
(lazy-cat (repeat (dec period) nil)
(map average (partition period 1 coll))))
@eldritchideen
Copy link
Author

Validated it against the following python pandas code:

In [14]:
nums = pd.Series([1,2,3,4,5,6,7,8,9,10,11])
pd.rolling_mean(nums,5)

Out[14]:
0    NaN
1    NaN
2    NaN
3    NaN
4      3
5      4
6      5
7      6
8      7
9      8
10     9
dtype: float64

Clojure result

scratch.core=> (ma 5 [1,2,3,4,5,6,7,8,9,10,11])
(nil nil nil nil 3 4 5 6 7 8 9)

@eldritchideen
Copy link
Author

Another interesting implementation from StackOverflow

(defn moving-average
  "Calculates the moving average of values with the given period.
  Returns a lazy seq, works with infinite input sequences.
  Does not include initial zeros in the output."
  [period values]
  (let [gen (fn gen [last-sum values-old values-new]
              (if (empty? values-new)
                nil
                (let [num-out (first values-old)
                      num-in  (first values-new)
                      new-sum (+ last-sum (- num-out) num-in)]
                  (lazy-seq
                    (cons new-sum
                          (gen new-sum
                               (next values-old)
                               (next values-new)))))))]
    (if (< (count (take period values)) period)
      nil
      (map #(/ % period)
           (gen (apply + (take (dec period) values))
                (cons 0 values)
                (drop (dec period) values))))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment