2 ;;; Copyright (c) 2005--2009, by A.J. Rossini <blindglobe@gmail.com>
3 ;;; See COPYRIGHT file for any additional restrictions (BSD license).
4 ;;; Since 1991, ANSI was finally finished. Edited for ANSI Common Lisp.
6 ;;; XLisp-ism's removed to focus on Common Lisp. Original source from:
7 ;;;; statistics.lsp XLISP-STAT statistics functions
8 ;;;; XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney
9 ;;;; Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz
10 ;;;; You may give out copies of this software; for conditions see the file
11 ;;;; COPYING included with this distribution.
13 (in-package :lisp-stat-descriptive-statistics
)
16 ;;; Basic Summary Statistics
20 (:documentation
"compute the mean of lists, vectors, various objects")
24 (:method
((x vector-like
))
26 (type (if (column-vector-p x
) :column
:row
)))
28 (ecase type
(:row
1) (:column n
))
29 (ecase type
(:row n
) (:column
1))))
34 Returns the mean of the elements x. Vector reducing.
36 FIXME: Why is this so complex? When figure out, put into generic."
39 (labels ((add-to-mean (x)
40 (let ((count+1 (+ count
1.0)))
41 (setf mean
(+ (* (/ count count
+1) mean
) (* (/ count
+1) x
)))
42 (setf count count
+1)))
46 (let ((seq (compound-data-seq x
)))
49 (if (numberp x
) (add-to-mean x
) (find-mean x
)))
50 (let ((n (length seq
)))
53 (let ((x (aref seq i
)))
56 (find-mean x
))))))))))
61 ;; We do the variance, since the SD is simply the root.
62 (defgeneric variance
(x)
63 (:documentation
"compute the variance of the entity X, i.e. if a
64 scalar, vector, or matrix.")
68 (sqrt (* (mean (* r r
)) (/ n
(- n
1))))))
69 (:method
((x vector-like
))))
71 (defgeneric standard-deviation
(x)
72 (:documentation
"Compute standard deivation of entity X.")
73 (:method
((x vector-like
)) (sqrt (variance x
)))
75 ;; if elements are not numeric, error, otherwise
77 (:method
((x matrix-like
))
78 (error "FIXME: define SD for matrix-like objects")))
80 (defun standard-deviation-fn (x)
82 Returns the standard deviation of the elements x. Vector reducing.
84 FIXME AJR: This should be redone as square-root of the variance, and
85 defer to that structure for computation."
86 (let ((n (count-elements x
))
88 (sqrt (* (mean (* r r
)) (/ n
(- n
1))))))
90 (defgeneric quantile
(x p
)
91 (:documentation
"Returns the P-th quantile(s) of sequence X.")
92 (:method
((x sequence
) (p sequence
))
93 (let* ((x (sort-data x
))
98 (/ (+ (select x low
) (select x high
)) 2)))
99 (:method
((x sequence
) (p real
))
100 (error "FIXME: implement.")))
103 ;;; things to build on top of quantiles...!
106 ;; Returns the median of the elements of X.
109 ;; (macroexpand '(median (list 1 2 3)))
110 ;; (median (list 1 2 3))
113 ;; Args: (number-data)
114 ;; Returns the interquartile range of the elements of X.
115 (defmacro interquartile-range
(x)
116 `(reduce #'-
(quantile ,x
'(0.75
0.25))))
120 Returns the five number summary (min, 1st quartile, medinan, 3rd quartile,
121 max) of the elements X."
122 (quantile x
'(0 .25 .5 .75 1)))
124 (defun covariance-matrix (&rest args
)
126 Returns the sample covariance matrix of the data columns in ARGS. ARGS may
127 consist of lists, vectors or matrices."
128 (let ((columns (apply #'append
129 (mapcar #'(lambda (x)
130 (if (typep x
'matrix-like
)
134 (/ (cross-product (reduce #'bind-columns
135 (- columns
(mapcar #'mean columns
))))
136 (- (length (car columns
)) 1))))
138 ;;;; Sampling / Resampling
140 (defun sample (x ssize
&optional replace
)
141 "Args: (x n &optional (replace nil))
142 Returns a list of a random sample of size N from sequence X drawn with or
143 without replacement."
146 (x (if (consp x
) (coerce x
'vector
) (copy-vector x
)))
149 (dotimes (i ssize result
)
150 (let ((j (if replace
(random n
) (+ i
(random (- n i
))))))
151 (setf result
(cons (aref x j
) result
))
152 (unless replace
;; swap elements i and j
153 (let ((temp (aref x i
)))
154 (setf (aref x i
) (aref x j
))
155 (setf (aref x j
) temp
))))))))