diff --git a/src/net/cgrand/xforms.cljc b/src/net/cgrand/xforms.cljc index 9de4fa6..6028477 100644 --- a/src/net/cgrand/xforms.cljc +++ b/src/net/cgrand/xforms.cljc @@ -361,6 +361,7 @@ (rf acc curr)))))))))) (def avg (reduce rf/avg)) +(def sd (reduce rf/sd)) (defn window "Returns a transducer which computes an accumulator over the last n items diff --git a/src/net/cgrand/xforms/rfs.cljc b/src/net/cgrand/xforms/rfs.cljc index 4d9f80d..304a0be 100644 --- a/src/net/cgrand/xforms/rfs.cljc +++ b/src/net/cgrand/xforms/rfs.cljc @@ -58,9 +58,24 @@ ([] (transient [0 0])) ([[n sum]] (/ sum n)) ([acc x] (avg acc x 1)) - ([[n sum :as acc] x w] + ([[n sum :as acc] x w] ; weighted mean (-> acc (assoc! 0 (+ n w)) (assoc! 1 (+ sum (* w x)))))) +(defn sd + "Reducing fn to compute the standard deviation. Returns 0 if no or only one item." + ([] #?(:clj (double-array 3) :cljs #js [0.0 0.0 0.0])) + ([^doubles a] + (let [s (aget a 0) s2 (aget a 1) n (aget a 2)] + (if (< 1 n) + (Math/sqrt (/ (- s2 (/ (* s s) n)) (dec n))) + 0.0))) + ([^doubles a x] + (let [s (aget a 0) s2 (aget a 1) n (aget a 2)] + (doto a + (aset 0 (+ s x)) + (aset 1 (+ s2 (* x x))) + (aset 2 (inc n)))))) + (defn last "Reducing function that returns the last value." ([] nil)