65 lines
1.7 KiB
Common Lisp
65 lines
1.7 KiB
Common Lisp
;;;; -*- mode: common-lisp; coding: utf-8; -*-
|
|
|
|
(defpackage ml-survey/stats
|
|
(:use #:cl)
|
|
(:export #:preprocess-and-transpose
|
|
#:calculate-statistics
|
|
#:stdev
|
|
#:average
|
|
#:median
|
|
#:geomean))
|
|
|
|
(in-package #:ml-survey/stats)
|
|
|
|
(defun preprocess-and-transpose (data)
|
|
(apply #'mapcar #'list (mapcar #'cdr data)))
|
|
|
|
(defun calculate-statistics (numbers)
|
|
(list :median (median numbers)
|
|
:average (average numbers)
|
|
:geomean (geomean numbers)
|
|
:stdev (stdev numbers)
|
|
:min (reduce #'min numbers)
|
|
:max (reduce #'max numbers)))
|
|
|
|
(defun average (numbers)
|
|
(if (null numbers)
|
|
0
|
|
(* 1.0 (/ (reduce #'+ numbers)
|
|
(length numbers)))))
|
|
|
|
(defun geomean (numbers)
|
|
(if (null numbers)
|
|
0
|
|
(expt (reduce #'* numbers)
|
|
(/ 1.0 (length numbers)))))
|
|
|
|
(defun median-odd (numbers)
|
|
(nth (floor (length numbers) 2) numbers))
|
|
|
|
(defun median-even (numbers)
|
|
(let* ((mid (floor (length numbers) 2))
|
|
(pair (list (nth (1- mid) numbers)
|
|
(nth mid numbers))))
|
|
(average pair)))
|
|
|
|
(defun median (numbers)
|
|
(let ((sorted (sort (copy-list numbers) #'<)))
|
|
(if (oddp (length sorted))
|
|
(median-odd sorted)
|
|
(median-even sorted))))
|
|
|
|
(defun range (numbers)
|
|
(- (reduce #'max numbers)
|
|
(reduce #'min numbers)))
|
|
|
|
(defun variance (numbers)
|
|
(if (< (length numbers) 2)
|
|
nil ; or we could return nil to indicate undefined variance
|
|
(let* ((n (length numbers))
|
|
(average-value (average numbers))
|
|
(squared-diff (mapcar (lambda (x) (expt (- x average-value) 2)) numbers)))
|
|
(/ (reduce #'+ squared-diff) (1- n)))))
|
|
|
|
(defun stdev (numbers)
|
|
(sqrt (variance numbers)))
|