;;;; ;;;; sir--i-ii-model.lsp XLISP-STAT sir-i-ii model proto and methods ;;;; sir 1.0 Copyright (c) 1990 by Ker-Chau Li ;;;; XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney ;;;; Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz ;;;; You may give out copies of this software; for conditions see the file ;;;; COPYING included with this distribution. ;;;; ;;;; ;;;; ;;;; Sir-I-II Model Prototype ;;;; ;;;; (defproto sir-I-II-model-proto '(x y nslice eigen-vectors1 eigen-values1 total-evalue1 eigen-vectors2 eigen-values2 total-evalue2) () *object* "Sliced Inverse Regression ( I & II ) Model") (defun sir-I-II-model (x y &key (print T)) "Args: (x y &key(print T)) X - list of independent variables (list of lists) Y - dependent variable. PRINT - if not NIL print summary information and plot sir1-y-sir2 Returns a sir model object. To examine the model further assign the result to a variable and send it messages. Messages include : x - original independent variables std-x - standard-deviation of x (a list) matrix-x - matrix form of x y - original dependent variable sir11 - the variable for the first direction of SIR1 sir12 - the variable for the second direction of SIR1 sir13 - the variable for the third direction of SIR1 sir21 - the variable for the first direction of SIR2 sir22 - the variable for the second direction of SIR2 sir23 - the variable for the third direction of SIR2 newx1 - the list of variables for all SIR1 directions newx2 - the list of variables for all SIR2 directions nobs - # of observations in the data set dim - # of independent variables eigen-values1 - list of all eigenvalues for SIR1 eigen-vectors1 - list of eigenvectors for SIR1 (in list form) std-eigen-vectors1 - standardized eigen-vectors of SIR1 (in list form) total-evalue1 - sum of all eigenvalues for SIR1 eigen-values2 - list of all eigenvalues for SIR2 eigen-vectors2 - list of eigenvectors for SIR2 (in list form) std-eigen-vectors2 - standardized eigen-vectors of SIR2 (in list form) total-evalue2 - sum of all eigenvalues for SIR2 p-values1 - p-values for checking if directions found by SIR1 are real. if only the first k p-values are needed, use the format : :p-values :only k nslice - # of slices used plot11 - spin-plot of sir11-y-sir12 plot12 - spin-plot of sir11-sir12-sir13 plot21 - spin-plot of sir21-y-sir22 plot22 - spin-plot of sir21-sir22-sir23" (let ( (m (send sir-I-II-model-proto :new)) ) (send m :x x) (send m :y y) (send m :compute) (if print (send m :display)) m)) (defmeth sir-I-II-model-proto :isnew () (send self :needs-computing t)) (defmeth sir-I-II-model-proto :save () `(sir-I-II-model',(send self :x) ',(send self :y) )) (defmeth sir-I-II-model-proto :compute () (let*( (x (send self :x)) (y (send self :y)) (sir-I-II-out (sir-I-II-no-output x y)) ) (setf (slot-value 'x) x) (setf (slot-value 'y) y) (setf (slot-value 'nslice) (nth 2 sir-I-II-out)) (setf (slot-value 'eigen-vectors1) (nth 0 (nth 0 sir-I-II-out))) (setf (slot-value 'eigen-values1) (nth 1 (nth 0 sir-I-II-out))) (setf (slot-value 'total-evalue1) (nth 2 (nth 0 sir-I-II-out))) (setf (slot-value 'eigen-vectors2) (nth 0 (nth 1 sir-I-II-out))) (setf (slot-value 'eigen-values2) (nth 1 (nth 1 sir-I-II-out))) (setf (slot-value 'total-evalue2) (nth 2 (nth 1 sir-I-II-out))) )) (defmeth sir-I-II-model-proto :needs-computing (&optional set) (if set (setf (slot-value 'nslice) nil)) (null (slot-value 'nslice))) (defmeth sir-I-II-model-proto :display () (let ( (evt1 (send self :eigen-vectors1)) (evt2 (send self :eigen-vectors2)) (sevt1 (send self :std-eigen-vectors1)) (sevt2 (send self :std-eigen-vectors2)) ) (format t "~%=========================================================") (format t "~% *** Sliced Inverse Regression Model ***~2%") (format t "Number of observation: ~s" (send self :nobs)) (format t "~2%Number of independent variables: ~s" (send self :dim)) (format t "~2%Number of slices: ~s" (send self :nslice)) (format t "~2%=========================================================") (format t "~% *** SIR-I ***") (format t "~2%the first direction found by SIR-I:~%") (format t "~s" (nth 0 evt1)) (format t "~2%the second direction found by SIR-I:~%") (format t "~S"(nth 1 evt1)) (format t "~2%the third direction found by SIR-I:~%") (format t "~s"(nth 2 evt1)) (format t "~2%the first <> direction found by SIR-I:~%") (format t "~s" (nth 0 sevt1)) (format t "~2%the second <> direction found by SIR-I:~%") (format t "~S"(nth 1 sevt1)) (format t "~2%the third <> direction found by SIR-I:~%") (format t "~s"(nth 2 sevt1)) (format t "~2%the companion output eigenvalues of SIR-I:~%") (format t "~s"(send self :eigen-values1)) (format t "~2%the sum of all eigenvalues for SIR-I:~%") (format t "~s"(send self :total-evalue1)) (format t "~2%=========================================================") (format t "~% *** SIR-II ***") (format t "~2%the first direction found by SIR-II:~%") (format t "~s" (nth 0 evt2)) (format t "~2%the second direction found by SIR-II:~%") (format t "~S"(nth 1 evt2)) (format t "~2%the third direction found by SIR-II:~%") (format t "~s"(nth 2 evt2)) (format t "~2%the first <> direction found by SIR-II:~%") (format t "~s" (nth 0 sevt2)) (format t "~2%the second <> direction found by SIR-II:~%") (format t "~S"(nth 1 sevt2)) (format t "~2%the third <> direction found by SIR-II:~%") (format t "~s"(nth 2 sevt2)) (format t "~2%the companion output eigenvalues of SIR-II:~%") (format t "~s"(send self :eigen-values2)) (format t "~2%the sum of all eigenvalues for SIR-II:~%") (format t "~s"(send self :total-evalue2)) (format t "~2%=========================================================~%") (send self :plot11) ; (send self :plot12) (send self :plot21) ; (send self :plot22) )) (defmeth sir-I-II-model-proto :x (&optional new-x) (when new-x (setf (slot-value 'x) new-x) (send self :needs-computing t)) (slot-value 'x)) (defmeth sir-I-II-model-proto :y (&optional new-y) (when new-y (setf (slot-value 'y) new-y) (send self :needs-computing t)) (slot-value 'y)) (defmeth sir-I-II-model-proto :eigen-values1 () (slot-value 'eigen-values1)) (defmeth sir-I-II-model-proto :eigen-vectors1 () (slot-value 'eigen-vectors1)) (defmeth sir-I-II-model-proto :total-evalue1 () (slot-value 'total-evalue1)) (defmeth sir-I-II-model-proto :eigen-values2 () (slot-value 'eigen-values2)) (defmeth sir-I-II-model-proto :eigen-vectors2 () (slot-value 'eigen-vectors2)) (defmeth sir-I-II-model-proto :total-evalue2 () (slot-value 'total-evalue2)) (defmeth sir-I-II-model-proto :newx1 () (let*( (mx (send self :matrix-x)) (nx1 (copy-list (send self :x))) (evector1 (send self :eigen-vectors1)) ) (dotimes (i (send self :dim)) (setf (nth i nx1) (coerce (%* mx (nth i evector1)) 'list))) nx1)) (defmeth sir-I-II-model-proto :newx2 () (let*( (mx (send self :matrix-x)) (nx2 (copy-list (send self :x))) (evector2 (send self :eigen-vectors2)) ) (dotimes (i (send self :dim)) (setf (nth i nx2) (coerce (%* mx (nth i evector2)) 'list))) nx2)) (defmeth sir-I-II-model-proto :sir11 () (let*( (mx (send self :matrix-x)) (ev11 (nth 0 (send self :eigen-vectors1))) ) (coerce (%* mx ev11) 'list))) (defmeth sir-I-II-model-proto :sir12 () (let*( (mx (send self :matrix-x)) (ev12 (nth 1 (send self :eigen-vectors1))) ) (coerce (%* mx ev12) 'list))) (defmeth sir-I-II-model-proto :sir13 () (let*( (mx (send self :matrix-x)) (ev13 (nth 2 (send self :eigen-vectors1))) ) (coerce (%* mx ev13) 'list))) (defmeth sir-I-II-model-proto :sir21 () (let*( (mx (send self :matrix-x)) (ev21 (nth 0 (send self :eigen-vectors2))) ) (coerce (%* mx ev21) 'list))) (defmeth sir-I-II-model-proto :sir22 () (let*( (mx (send self :matrix-x)) (ev22 (nth 1 (send self :eigen-vectors2))) ) (coerce (%* mx ev22) 'list))) (defmeth sir-I-II-model-proto :sir23 () (let*( (mx (send self :matrix-x)) (ev23 (nth 2 (send self :eigen-vectors2))) ) (coerce (%* mx ev23) 'list))) (defmeth sir-I-II-model-proto :std-x () (stand (send self :x))) (defmeth sir-I-II-model-proto :std-eigen-vectors1 () (let*( (std-x (send self :std-x)) (dim (length std-x)) (eigen-vectors1 (send self :eigen-vectors1)) (std-eigen-vectors1 (repeat (list (repeat 0 dim)) dim)) ) (dotimes (i dim) (setf (nth i std-eigen-vectors1) (* (nth i eigen-vectors1) std-x))) std-eigen-vectors1)) (defmeth sir-I-II-model-proto :std-eigen-vectors2 () (let*( (std-x (send self :std-x)) (dim (length std-x)) (eigen-vectors2 (send self :eigen-vectors2)) (std-eigen-vectors2 (repeat (list (repeat 0 dim)) dim)) ) (dotimes (i dim) (setf (nth i std-eigen-vectors2) (* (nth i eigen-vectors2) std-x))) std-eigen-vectors2)) (defmeth sir-I-II-model-proto :matrix-x () (let*( (x (send self :x)) (dim (send self :dim)) (nobs (send self :nobs)) (mx (transpose (make-array (list dim nobs) :initial-contents x))) ) mx)) (defmeth sir-I-II-model-proto :nobs () (length (send self :y))) (defmeth sir-I-II-model-proto :dim () (length (send self :x))) (defmeth sir-I-II-model-proto :p-values1 (&key (only nil)) (let*( (dim (send self :dim)) (nobs (send self :nobs)) (evl (send self :eigen-values1)) (tev (send self :total-evalue1)) (ns (send self :nslice)) (dim1 (if only only dim)) count pv ) (dotimes (i dim1) (setf count (+ i 1)) (setf pv (- 1 (chisq-cdf (* nobs tev) (* (- dim i) (- ns count))))) (setf tev (- tev (nth i evl))) (format t "~%P-value for checking if the ~s-th component for SIRIis real: ~s~%" count pv) ) (format t "~%") )) ;;(defmeth sir-I-II-model-proto :p-values2 (&key (only nil)) ;; (let*( ;; (dim (send self :dim)) ;; (nobs (send self :nobs)) ;; (evl (send self :eigen-values2)) ;; (tev (send self :total-evalue2)) ;; (ns (send self :nslice)) ;; (dim1 (if only only dim)) ;; count ;; pv ;; ) ;; (dotimes (i dim1) ;; (setf count (+ i 1)) ;; (setf pv (- 1 (chisq-cdf (* nobs tev) (* (- dim i) (- ns count))))) ;; (setf tev (- tev (nth i evl))) ;; (format t "~%P-value for checking if the ~s-th component for SIRIIis real: ~s~%" ;;count pv) ;; ) ;; (format t "~%") ;; )) (defmeth sir-I-II-model-proto :nslice () (slot-value 'nslice)) (defmeth sir-I-II-model-proto :plot11 () (setf plot11 (spin-plot (list (send self :sir11) (send self :y) (send self :sir12)) :variable-labels (list "sirI-1" "y" "sirI-2") :title "Sir-I-view: sirI-1-y-sirI-2")) (send plot11 :linked t) ) (defmeth sir-I-II-model-proto :plot12 () (setf plot12 (spin-plot (list (send self :sir11) (send self :sir12) (send self :sir13)) :variable-labels (list "sirI-1" "sirI-2" "sirI-3") :title "Sir-I-view: sirI-1 - sirI-2 - sirI-3")) (send plot12 :linked t) ) (defmeth sir-I-II-model-proto :plot21 () (setf plot21 (spin-plot (list (send self :sir21) (send self :y) (send self :sir22)) :variable-labels (list "sirII-1" "y" "sirII-2") :title "Sir-II-view: sirII-1-y-sirII-2")) (send plot21 :linked t) ) (defmeth sir-I-II-model-proto :plot22 () (setf plot22 (spin-plot (list (send self :sir21) (send self :sir22) (send self :sir23)) :variable-labels (list "sirII-1" "sirII-2" "sirII-3") :title "Sir-II-view: sirII-1 - sirII-2 - sirII-3")) (send plot22 :linked t) ) ;;======================================================================= (defun sir-I-II-no-output ( x y) "sir-I-II" (let* ( (y-order (order y)) (nobs (length y)) (dim (length x)) (x-mat (transpose (make-array (list dim nobs) :initial-contents x))) (cov-x (covariance-matrix1 x-mat )) (cov-x-inv (inverse cov-x)) (nslice (nth 0 (get-value-dialog "number of slices" ))) (ncase1(floor (/ nobs nslice))) (nslice2 (- nobs (* ncase1 nslice))) (nslice1 (- nslice nslice2)) (ncase2( + ncase1 1)) (iseq-ncase (iseq 0 (- ncase1 1))) (case (select y-order iseq-ncase)) (iseq-dim (iseq 0 (- dim 1))) (x-slice (select x-mat case iseq-dim)) (covx-slice (list (covariance-matrix1 x-slice))) (ave-covx (car (copy-list covx-slice))) (evv1 (repeat 0 dim)) (evector1 (repeat 0 dim)) (evv2 (repeat 0 dim)) (evector2 (repeat 0 dim)) cov-3 meat1 evalues1 total-evalue1 order-evalue1 ev1 meat2 evalues2 total-evalue2 order-evalue2 ev2 ) (dotimes (i (- nslice1 1)) (setf iseq-ncase (+ iseq-ncase ncase1)) (setf case (select y-order iseq-ncase)) (setf x-slice (select x-mat case iseq-dim)) (setf covx-slice(append covx-slice (list (covariance-matrix1 x-slice))))) (setf iseq-ncase (append (list (- (nth 0 iseq-ncase) 1)) iseq-ncase)) (dotimes (i nslice2 ) (setf iseq-ncase(+ iseq-ncase ncase2)) (setf case (select y-order iseq-ncase)) (setf x-slice (select x-mat case iseq-dim)) (setf covx-slice (append covx-slice (list (covariance-matrix1 x-slice))))) (dotimes (i (- nslice1 1)) (setf ave-covx (+ ave-covx (nth (+ 1 i) covx-slice))) ) (setf ave-covx (/ (* ave-covx ncase1 ) nobs)) (dotimes (i nslice2 ) (setf ave-covx (+ ave-covx (/ (* ncase2 (nth (+ nslice1 i) covx-slice)) nobs) ))) (setf meat1 (eigen-decomp (- cov-x ave-covx) cov-x)) (setf evalues1 (coerce (nth 1 meat1) 'list)) (setf total-evalue1 (sum evalues1)) ;; (setf ev1 (coerce (nth 0 meat1) 'list)) (setf ev1 (mapcar #'coerce (row-list (nth 0 meat1)) (repeat 'list dim))) (setf order-evalue1 (reverse (order evalues1))) (setf evalues1 (reverse (sort-data evalues1))) (dotimes (i dim) (setf (nth i evv1) (coerce (nth (nth i order-evalue1) ev1) 'list)) ) ;;==================================================================== (dotimes (i nslice) (setf (nth i covx-slice) (- (nth i covx-slice) ave-covx)) ) (setf cov-3 (%* (%* (nth 0 covx-slice) cov-x-inv) (nth 0 covx-slice))) (dotimes (i (- nslice1 1)) (setf cov-3 (+ cov-3 (%* (%* (nth (+ i 1) covx-slice ) cov-x-inv) (nth (+ i 1) covx-slice)))) ) (setf cov-3 (* cov-3 (/ ncase1 nobs))) (dotimes (i nslice2) (setf cov-3 (+ cov-3 (* (%* (%* (nth (+ i nslice1) covx-slice ) cov-x-inv) (nth (+ i 1) covx-slice)) (/ ncase2 nobs) ))) ) (setf meat2 (eigen-decomp cov-3 cov-x)) (setf evalues2 (coerce (nth 1 meat2) 'list)) (setf total-evalue2 (sum evalues2)) ;; (setf ev2 (coerce (nth 0 meat2) 'list)) (setf ev2 (mapcar #'coerce (row-list (nth 0 meat2)) (repeat 'list dim))) (setf order-evalue2 (reverse (order evalues2))) (setf evalues2 (reverse (sort-data evalues2))) (dotimes (i dim) (setf (nth i evv2) (coerce (nth (nth i order-evalue2) ev2) 'list)) ) (list (list evv1 evalues1 total-evalue1) (list evv2 evalues2 total-evalue2) nslice) ))