aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/clojure/contrib/accumulators.clj41
-rw-r--r--src/clojure/contrib/accumulators/examples.clj7
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))