Bulletproof statistical functions
This commit is contained in:
parent
f8c0d2d0c6
commit
1a65165015
2 changed files with 31 additions and 13 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
(defsystem "dev.metalisp.survey"
|
(defsystem "dev.metalisp.survey"
|
||||||
:description "A simple survey"
|
:description "A simple survey"
|
||||||
:version "0.4.6"
|
:version "0.4.7"
|
||||||
:author "Marcus Kammer <marcus.kammer@metalisp.dev>"
|
:author "Marcus Kammer <marcus.kammer@metalisp.dev>"
|
||||||
:source-control "git@git.sr.ht:~marcuskammer/dev.metalisp.survey"
|
:source-control "git@git.sr.ht:~marcuskammer/dev.metalisp.survey"
|
||||||
:licence "MIT"
|
:licence "MIT"
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
(in-package #:ml-survey/stats)
|
(in-package #:ml-survey/stats)
|
||||||
|
|
||||||
|
(define-condition stats-error (error)
|
||||||
|
((message :initarg :message :reader error-message)))
|
||||||
|
|
||||||
(defun preprocess-and-transpose (data)
|
(defun preprocess-and-transpose (data)
|
||||||
(apply #'mapcar #'list (mapcar #'cdr data)))
|
(apply #'mapcar #'list (mapcar #'cdr data)))
|
||||||
|
|
||||||
|
@ -21,19 +24,34 @@
|
||||||
(reduce #'max numbers)))
|
(reduce #'max numbers)))
|
||||||
|
|
||||||
(defun standard-deviation (numbers)
|
(defun standard-deviation (numbers)
|
||||||
(let* ((avg (mean numbers))
|
(handler-case
|
||||||
(variance (/ (reduce #'+ (mapcar (lambda (x) (expt (- x avg) 2)) numbers))
|
(let ((len (length numbers)))
|
||||||
(1- (length numbers)))))
|
(if (< len 2)
|
||||||
(sqrt variance)))
|
(error 'stats-error :message "Need at least two numbers for standard deviation")
|
||||||
|
(let ((avg (mean numbers)))
|
||||||
|
(sqrt (/ (reduce #'+ (mapcar (lambda (x) (expt (- x avg) 2)) numbers))
|
||||||
|
(1- len))))))
|
||||||
|
(type-error ()
|
||||||
|
(error 'stats-error :message "Invalid input for standard deviation calculation"))))
|
||||||
|
|
||||||
(defun mean (numbers)
|
(defun mean (numbers)
|
||||||
(/ (reduce #'+ numbers) (length numbers)))
|
(handler-case
|
||||||
|
(if (null numbers)
|
||||||
|
(error 'stats-error :message "Cannot calculate mean of an empty list")
|
||||||
|
(/ (reduce #'+ numbers) (length numbers)))
|
||||||
|
(division-by-zero ()
|
||||||
|
(error 'stats-error :message "Division by zero in mean calculation"))))
|
||||||
|
|
||||||
(defun median (numbers)
|
(defun median (numbers)
|
||||||
(let ((sorted (sort (copy-seq numbers) #'<))
|
(handler-case
|
||||||
(count (length numbers)))
|
(let ((sorted (sort (copy-seq numbers) #'<))
|
||||||
(if (oddp count)
|
(len (length numbers)))
|
||||||
(nth (floor count 2) sorted)
|
(if (zerop len)
|
||||||
(/ (+ (nth (1- (/ count 2)) sorted)
|
(error 'stats-error :message "Cannot calculate median of an empty list")
|
||||||
(nth (/ count 2) sorted))
|
(if (oddp len)
|
||||||
2.0))))
|
(nth (floor len 2) sorted)
|
||||||
|
(/ (+ (nth (1- (/ len 2)) sorted)
|
||||||
|
(nth (/ len 2) sorted))
|
||||||
|
2))))
|
||||||
|
(type-error ()
|
||||||
|
(error 'stats-error :message "Invalid input for median calculation"))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue