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 (defpackage :lisp-stat
16 (:export standard-deviation quantile median interquartile-range
17 fivnum covariance-matrix difference rseq matrix print-matrix solve
18 backsolve eigenvalues eigenvectors accumulate cumsum combine
21 (:in-package
:lisp-stat
)
24 ;;;; Basic Summary Statistics
27 (defun standard-deviation (x)
29 Returns the standard deviation of the elements x. Vector reducing."
30 (let ((n (count-elements x
))
32 (sqrt (* (mean (* r r
)) (/ n
(- n
1))))))
36 Returns the P-th quantile(s) of sequence X. P can be a number or a sequence."
37 (let* ((x (sort-data x
))
42 (/ (+ (select x low
) (select x high
)) 2)))
46 Returns the median of the elements of X."
49 (defun interquartile-range (x)
51 Returns the interquartile range of the elements of X."
52 (apply #'-
(quantile x
'(0.75
0.25))))
56 Returns the five number summary (min, 1st quartile, medinan, 3rd quartile,
57 max) of the elements X."
58 (quantile x
'(0 .25 .5 .75 1)))
60 (defun covariance-matrix (&rest args
)
62 Returns the sample covariance matrix of the data columns in ARGS. ARGS may
63 consist of lists, vectors or matrices."
64 (let ((columns (apply #'append
66 (if (matrixp x
) (column-list x
) (list x
)))
68 (/ (cross-product (apply #'bind-columns
69 (- columns
(mapcar #'mean columns
))))
70 (- (length (car columns
)) 1))))
73 ;;;; Basic Sequence Operations
78 Returns differences for a sequence X."
80 (- (select x
(iseq 1 (1- n
))) (select x
(iseq 0 (- n
2))))))
84 Returns a list of NUM equally spaced points starting at A and ending at B."
85 (+ a
(* (iseq 0 (1- num
)) (/ (float (- b a
)) (1- num
)))))
88 ;;;; Linear Algebra Functions
91 (defun matrix (dim data
)
93 returns a matrix of dimensions DIM initialized using sequence DATA
95 (let ((dim (coerce dim
'list
))
96 (data (coerce data
'list
)))
97 (make-array dim
:initial-contents
(split-list data
(nth 1 dim
)))))
99 (defun print-matrix (a &optional
(stream *standard-output
*))
100 "Args: (matrix &optional stream)
101 Prints MATRIX to STREAM in a nice form that is still machine readable"
102 (unless (matrixp a
) (error "not a matrix - ~a" a
))
103 (let ((size (min 15 (max (map-elements #'flatsize a
)))))
104 (format stream
"#2a(~%")
105 (dolist (x (row-list a
))
107 (let ((n (length x
)))
109 (let ((y (aref x i
)))
111 ((integerp y
) (format stream
"~vd" size y
))
112 ((floatp y
) (format stream
"~vg" size y
))
113 (t (format stream
"~va" size y
))))
114 (if (< i
(- n
1)) (format stream
" "))))
115 (format stream
")~%"))
116 (format stream
" )~%")
121 Solves A x = B using LU decomposition and backsolving. B can be a sequence
123 (let ((lu (lu-decomp a
)))
125 (apply #'bind-columns
126 (mapcar #'(lambda (x) (lu-solve lu x
)) (column-list b
)))
129 (defun backsolve (a b
)
131 Solves A x = B by backsolving, assuming A is upper triangular. B must be a
132 sequence. For use with qr-decomp."
133 (let* ((n (length b
))
134 (sol (make-array n
)))
140 (setq val
(- val
(* (aref sol l
) (aref a k l
))))))
141 (setf (aref sol k
) (/ val
(aref a k k
)))))
142 (if (listp b
) (coerce sol
'list
) sol
)))
144 (defun eigenvalues (a)
146 Returns list of eigenvalues of square, symmetric matrix A"
149 (defun eigenvectors (a)
151 Returns list of eigenvectors of square, symmetric matrix A"
154 (defun accumulate (f s
)
156 Accumulates elements of sequence S using binary function F.
157 (accumulate #'+ x) returns the cumulative sum of x."
158 (let* ((result (list (elt s
0)))
160 (flet ((acc (dummy x
)
161 (rplacd tail
(list (funcall f
(first tail
) x
)))
162 (setf tail
(cdr tail
))))
164 (if (vectorp s
) (coerce result
'vector
) result
)))
168 Returns the cumulative sum of X."
171 (defun combine (&rest args
)
173 Returns sequence of elements of all arguments."
174 (copy-seq (element-seq args
)))
176 (defun lowess (x y
&key
(f .25) (steps 2) (delta -
1) sorted
)
177 "Args: (x y &key (f .25) (steps 2) delta sorted)
178 Returns (list X YS) with YS the LOWESS fit. F is the fraction of data used for
179 each point, STEPS is the number of robust iterations. Fits for points within
180 DELTA of each other are interpolated linearly. If the X values setting SORTED
181 to T speeds up the computation."
182 (let ((x (if sorted x
(sort-data x
)))
183 (y (if sorted y
(select y
(order x
))))
184 (delta (if (> delta
0.0) delta
(/ (- (max x
) (min x
)) 50))))
185 (list x
)));; (|base-lowess| x y f steps delta))))