lsfloat needed for mach-eps.
[CommonLispStat.git] / statistics.lsp
blobdd713047f2050c7f76dd1ff7e9d2ea081538687e
1 ;;; -*- mode: lisp -*-
2 ;;; Copyright (c) 2005--2007, 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 :cl-user)
15 (defpackage :lisp-stat-descriptive-statistics
16 (:use :common-lisp
17 :lisp-stat-data
18 :lisp-stat-math
19 :lisp-stat-compound-data
20 :lisp-stat-matrix
21 :lisp-stat-linalg-data
22 :lisp-stat-linalg
23 :lisp-stat-basics)
24 (:shadowing-import-from :lisp-stat-math
25 expt + - * / ** mod rem abs 1+ 1- log exp sqrt sin cos tan
26 asin acos atan sinh cosh tanh asinh acosh atanh float random
27 truncate floor ceiling round minusp zerop plusp evenp oddp
28 < <= = /= >= > complex conjugate realpart imagpart phase
29 min max logand logior logxor lognot ffloor fceiling
30 ftruncate fround signum cis)
31 (:export ;; descriptive stats
32 standard-deviation quantile median interquartile-range
33 fivnum
35 sample
40 (in-package :lisp-stat-descriptive-statistics)
42 ;;;;
43 ;;;; Basic Summary Statistics
44 ;;;;
46 (defun standard-deviation (x)
47 "Args: (x)
48 Returns the standard deviation of the elements x. Vector reducing."
49 (let ((n (count-elements x))
50 (r (- x (mean x))))
51 (sqrt (* (mean (* r r)) (/ n (- n 1))))))
54 ;; FIXME the following assume that we are using the vector based functions
55 (defun quantile (x p)
56 "Args: (x p)
57 Returns the P-th quantile(s) of sequence X. P can be a number or a sequence."
58 (let* ((x (sort-data x))
59 (n (length x))
60 (np (* p (- n 1)))
61 (low (floor np))
62 (high (ceiling np)))
63 (/ (+ (select x low) (select x high)) 2)))
65 (defun median (x)
66 "Args: (x)
67 Returns the median of the elements of X."
68 (quantile x 0.5))
70 (defun interquartile-range (x)
71 "Args: (number-data)
72 Returns the interquartile range of the elements of X."
73 (reduce #'- (quantile x '(0.75 0.25))))
75 (defun fivnum (x)
76 "Args: (number-data)
77 Returns the five number summary (min, 1st quartile, medinan, 3rd quartile,
78 max) of the elements X."
79 (quantile x '(0 .25 .5 .75 1)))
81 (defun covariance-matrix (&rest args)
82 "Args: (&rest args)
83 Returns the sample covariance matrix of the data columns in ARGS. ARGS may
84 consist of lists, vectors or matrices."
85 (let ((columns (apply #'append
86 (mapcar #'(lambda (x)
87 (if (matrixp x) (column-list x) (list x)))
88 args))))
89 (/ (cross-product (apply #'bind-columns
90 (- columns (mapcar #'mean columns))))
91 (- (length (car columns)) 1))))
93 ;;;; Sampling / Resampling
95 (defun sample (x ssize &optional replace)
96 "Args: (x n &optional (replace nil))
97 Returns a list of a random sample of size N from sequence X drawn with or
98 without replacement."
99 (check-sequence x)
100 (let ((n (length x))
101 (x (if (consp x) (coerce x 'vector) (copy-vector x)))
102 (result nil))
103 (if (< 0 n)
104 (dotimes (i ssize result)
105 (let ((j (if replace (random n) (+ i (random (- n i))))))
106 (setf result (cons (aref x j) result))
107 (unless replace ;; swap elements i and j
108 (let ((temp (aref x i)))
109 (setf (aref x i) (aref x j))
110 (setf (aref x j) temp))))))))
114 (defun mean (x)
115 "Args: (x)
116 Returns the mean of the elements x. Vector reducing."
117 (let ((mean 0.0)
118 (count 0.0))
119 (labels ((add-to-mean (x)
120 (let ((count+1 (+ count 1.0)))
121 (setf mean (+ (* (/ count count+1) mean) (* (/ count+1) x)))
122 (setf count count+1)))
123 (find-mean (x)
124 (if (numberp x)
125 (add-to-mean x)
126 (let ((seq (compound-data-seq x)))
127 (if (consp seq)
128 (dolist (x seq)
129 (if (numberp x) (add-to-mean x) (find-mean x)))
130 (let ((n (length seq)))
131 (dotimes (i n)
132 (declare (fixnum i))
133 (let ((x (aref seq i)))
134 (if (numberp x)
135 (add-to-mean x)
136 (find-mean x))))))))))
137 (find-mean x)
138 mean)))