54 lines
2.4 KiB
Racket
54 lines
2.4 KiB
Racket
#lang racket/base
|
|
(require math/private/statistics/quickselect)
|
|
|
|
;; racket's quantile uses "Method 1" of https://en.wikipedia.org/wiki/Quartile
|
|
;; Tukey (fivenum) uses "Method 2", so we will need a specialist median
|
|
(define (fivenum! data-v)
|
|
(define (tukey-median start end)
|
|
(define-values (n/2 parity) (quotient/remainder (- end start) 2))
|
|
(define mid (+ start n/2))
|
|
(if (zero? parity)
|
|
(/ (+ (data-kth-value! (+ mid (sub1 parity))) (data-kth-value! mid)) 2)
|
|
(data-kth-value! mid)))
|
|
|
|
(define n-data (let ((l (vector-length data-v)))
|
|
(if (zero? l)
|
|
(raise-argument-error 'data-v "nonempty (Vectorof Real)" data-v)
|
|
l)))
|
|
|
|
(define (data-kth-value! n) (kth-value! data-v n <))
|
|
|
|
(define subset-size (let-values (((n/2 parity) (quotient/remainder n-data 2))) (+ n/2 parity)))
|
|
|
|
(vector (data-kth-value! 0)
|
|
(tukey-median 0 subset-size)
|
|
(tukey-median 0 n-data)
|
|
(tukey-median (- n-data subset-size) n-data)
|
|
(data-kth-value! (sub1 n-data))))
|
|
|
|
(define (fivenum data-seq)
|
|
(fivenum! (if (and (vector? data-seq) (not (immutable? data-seq)))
|
|
data-seq
|
|
(for/vector ((datum data-seq)) datum))))
|
|
|
|
(module+ test
|
|
(require rackunit
|
|
racket/vector)
|
|
(check-equal? #(14 14 14 14 14) (fivenum #(14)) "Minimal case")
|
|
(check-equal? #(8 11 14 17 20) (fivenum #(8 14 20)) "3-value case")
|
|
(check-equal? #(8 11 15 18 20) (fivenum #(8 14 16 20)) "4-value case")
|
|
|
|
(define x1-seq #(36 40 7 39 41 15))
|
|
(define x1-v (vector-copy x1-seq))
|
|
(check-equal? x1-seq x1-v "before fivenum! sequence and vector were not `equal?`")
|
|
(check-equal? #(7 15 #e37.5 40 41) (fivenum! x1-v) "Test against Go results x1")
|
|
(check-not-equal? x1-seq x1-v "fivenum! did not mutate mutable input vectors")
|
|
|
|
(check-equal? #(6 #e25.5 40 #e42.5 49) (fivenum #(15 6 42 41 7 36 49 40 39 47 43)) "Test against Go results x2")
|
|
|
|
(check-equal? #(-1.95059594 -0.676741205 0.23324706 0.746070945 1.73131507)
|
|
(fivenum (vector 0.14082834 0.09748790 1.73131507 0.87636009 -1.95059594 0.73438555
|
|
-0.03035726 1.46675970 -0.74621349 -0.72588772 0.63905160 0.61501527
|
|
-0.98983780 -1.00447874 -0.62759469 0.66206163 1.04312009 -0.10305385
|
|
0.75775634 0.32566578))
|
|
"Test against Go results x3"))
|