diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/clojure/contrib/accumulators.clj | 41 | ||||
-rw-r--r-- | src/clojure/contrib/accumulators/examples.clj | 7 |
2 files changed, 46 insertions, 2 deletions
diff --git a/src/clojure/contrib/accumulators.clj b/src/clojure/contrib/accumulators.clj index 524bf7f7..d6de6a25 100644 --- a/src/clojure/contrib/accumulators.clj +++ b/src/clojure/contrib/accumulators.clj @@ -1,7 +1,7 @@ ;; Accumulators ;; by Konrad Hinsen -;; last updated April 17, 2009 +;; last updated April 21, 2009 ;; This module defines various accumulators (list, vector, map, ;; sum, product, counter, and combinations thereof) with a common @@ -218,6 +218,45 @@ (min-max new-min new-max))) ; +; Mean and variance accumulator +; +(deftype ::mean-variance mean-variance) + +(derive ::mean-variance ::accumulator) + +(defvar empty-mean-variance (mean-variance {:n 0 :mean 0 :variance 0}) + "An empty mean-variance accumulator, combining sample mean and + sample variance. Only numbers can be added.") + +(defmethod combine ::mean-variance + ([mv] + mv) + + ([mv1 mv2] + (let [{n1 :n mean1 :mean var1 :variance} mv1 + {n2 :n mean2 :mean var2 :variance} mv2 + n (+ n1 n2) + mean (/ (+ (* n1 mean1) (* n2 mean2)) n) + sq #(* % %) + c (+ (* n1 (sq (- mean mean1))) (* n2 (sq (- mean mean2)))) + var (if (< n 2) + 0 + (/ (+ c (* (dec n1) var1) (* (dec n2) var2)) (dec n)))] + (mean-variance {:n n :mean mean :variance var}))) + + ([mv1 mv2 & mvs] + (reduce combine (combine mv1 mv2) mvs))) + +(defmethod add ::mean-variance + [mv x] + (let [{n :n mean :mean var :variance} mv + n1 (inc n) + d (- x mean) + new-mean (+ mean (/ d n1)) + new-var (if (zero? n) 0 (/ (+ (* (dec n) var) (* d (- x new-mean))) n))] + (mean-variance {:n n1 :mean new-mean :variance new-var}))) + +; ; Counter accumulator ; (deftype ::counter counter) diff --git a/src/clojure/contrib/accumulators/examples.clj b/src/clojure/contrib/accumulators/examples.clj index ec3c1a01..f30483cc 100644 --- a/src/clojure/contrib/accumulators/examples.clj +++ b/src/clojure/contrib/accumulators/examples.clj @@ -12,7 +12,7 @@ empty-vector empty-list empty-queue empty-set empty-map empty-counter empty-counter-with-total empty-sum empty-product empty-maximum empty-minimum - empty-min-max empty-string empty-tuple)])) + empty-min-max empty-mean-variance empty-string empty-tuple)])) ; Vector accumulator: combine is concat, add is conj (combine [:a :b] [:c :d] [:x :y]) @@ -74,6 +74,11 @@ m2 (add-items empty-min-max [(/ 1 2)])] (combine m1 m2)) +; Mean-variance accumulator: sample mean and sample variance +(let [m1 (add-items empty-mean-variance [2 4]) + m2 (add-items empty-mean-variance [6])] + (combine m1 m2)) + ; String accumulator: combine is concatenation (combine "a" "b" "c" "def") (add "a" (char 44)) |