Psych 285: Computational Statistics
and Statistical VisualizationProfessor Forrest Young
ViSta Model Object Programming Example
To understand the examples presented here, you need to have Chapter 14 of the ViSta user's guide. This chapter is available as a Adobe Acrobat file, for which you need the Adobe Acrobat Reader. The chapter describes how to extend ViSta by adding new model objects. While it describes an earlier release of ViSta and is somewhat out of date, it is still accurate in general, and most details have not changed.
The code presented here is completely up-to-date and accurate, whereas the older code example in Chapter 14 is not. Until Chapter 14 is updated, I recommend that you compare the example in Chapter 14 with the examples presented here, and with the code in the pcamob.lsp file that comes with the program distribution.
Example 1: A simple ViSta regression model object.
This example show how to write a ViSta model object that uses an already existing XLispStat object. In this example a very simple model object is written to do univariate regression. It uses Luke Tierney's regression-model object to do the actual work. Thus, this example shows how to construct a ViSta model object that acts as an interface to the underlying XLS system.
(defproto reg-model-proto '(reg-object response predictors) () mv-model-object-proto)
(defmeth reg-model-proto :reg-object (&optional (object-id nil set)) (if set (setf (slot-value 'reg-object) object-id)) (slot-value 'reg-object)) (defmeth reg-model-proto :response (&optional (vector nil set)) (if set (setf (slot-value 'response) vector)) (slot-value 'response)) (defmeth reg-model-proto :predictors (&optional (matrix nil set)) (if set (setf (slot-value 'predictors) matrix)) (slot-value 'predictors))
(defmeth reg-model-proto :analysis ()
(let* ((response (send self :response))
(predictors (send self :predictors))
(object (regression-model predictors response :print nil))
)
(send self :reg-object object)
t))
(defmeth reg-model-proto :report (&key (dialog nil))
(send (send self :reg-object) :display))
(defmeth reg-model-proto :visualize ()
(send (send self :reg-object) :plot-bayes-residuals))
(none)
(defmeth reg-model-proto :isnew (response predictors &rest args)
(when (or (< (send *current-data* :active-nvar '(numeric)) 2)
(< (send *current-data* :active-nobs) 4))
(fatal-message "The minimum size data is 2 numeric variables and 4 observations"))
(send self :model-abbrev "REG")
(send self :response (send *current-data* :variable response))
(send self :predictors (apply #'bind-columns
(map-elements #'send *current-data* :variable predictors)))
(apply #'call-next-method args))
(defun reg (&key (data *current-data*) (title "Linear Regression") (name (strcat "REG-" (send *current-data* :name))) (dialog nil) (response nil) (predictors nil)) (if (not (eq *current-data* data)) (setcd data)) (send reg-model-proto :new response predictors 0 data title name dialog))
(load "abrasion")
(reg :response "Abrasion-Loss"
:predictors '("Hardness" "Tensile-Strength"))
The code is tested by creating instances of the object using various ViSta data objects. These results can be compared to the Data menu's Summarize Data item.
(defproto describe-model-proto '(moments quartiles) ()
mv-model-object-proto)
(defmeth describe-model-proto :moments (&optional (values nil set)) "Slot-Accessor method" (if set (setf (slot-value 'moments) values)) (slot-value 'moments)) (defmeth describe-model-proto :quartiles (&optional (values nil set)) "Slot-Accessor method" (if set (setf (slot-value 'quartiles) values)) (slot-value 'quartiles))
(defmeth describe-model-proto :options ()
)
(defmeth describe-model-proto :analysis ()
(let ((means (send self :means))
(stdvs (send self :standard-deviations))
(varis (send self :variances))
(skews (send self :skewnesses))
(kurts (send self :kurtoses))
(5nums (mapcar #'fivnum
(column-list
(send self :active-data-matrix '(numeric))))))
(send self :moments (list means stdvs varis skews kurts))
(send self :quartiles 5nums))
t)
(defmeth describe-model-proto :report (&key (dialog nil))
(if (not (eq current-object self)) (setcm self))
(let ((numeric-vars (send self :active-variables '(numeric)))
(moments-mat (apply #'bind-columns (send self :moments)))
(fivenum-mat (apply #'bind-rows (send self :quartiles)))
(w (report-header (send self :title)))
)
(display-string (format nil "Summary Statistics") w)
(display-string (format nil "~2%Moments") w)
(display-string (format nil "~%Means, Standard Deviations, Variances, Skewnesses & Kurtoses~%") w)
(print-matrix-to-window moments-mat w :labels numeric-vars :decimals 3)
(display-string (format nil "~2%Five Number Summary") w)
(display-string (format nil "~%Minimum, 1st Quartile, Median, 3rd Quartile, Maximum~%") w)
(print-matrix-to-window fivenum-mat w :labels numeric-vars :decimals 3)
)
t)
(defmeth describe-model-proto :visualize ()
"Method args: none
Plots the data. Produces histogram, scatterplot, spin-plot or scatterplot matrix, depending on the number of variables in the data."
(let* ((data (send self :active-data-matrix '(numeric)))
(title (send self :title))
(nvars (second (array-dimensions data))))
(cond
((= nvars 1) (histogram (column-list data) :title title))
((= nvars 2) (plot-points (column-list data) :title title))
((= nvars 3) (spin-plot (column-list data) :title title))
((and (> nvars 3) (< nvars 10))
(spread-plot
(matrix '(1 2)
(list
(scatterplot-matrix (column-list data) :title title)
(spin-plot (column-list data) :title title)))
:model self))
(t (error "Too Many Variables")))))
;(none for this example)
(defmeth describe-model-proto :isnew (&rest args)
(when (or (< (send *current-data* :active-nvar '(numeric)) 1)
(< (send *current-data* :active-nobs) 4))
(error "The minimum size data is one variable and 4 observations"))
(send self :model-abbrev "STS")
(apply #'call-next-method args))
(defun describe-data (&key (data *current-data*) (title "Data Summary Statistics") (name (strcat "STS-" (send *current-data* :name))) (dialog nil)) (if (not (eq *current-data* data)) (setcd data)) (send describe-model-proto :new 0 data title name dialog))
(load (strcat *vista-dir-name* "sprdplt1")) (load-data (strcat *data-dir-name* "cars")) (describe-data) (report-model) (visualize-model)
To get in touch:
email: forrest@unc.edu WWW: http://forrest.psych.unc.edu