update and inclusion of listoflist transform code.
[CommonLispStat.git] / src / data / listoflist.lisp
blobdf65c003f7e8ddc5940d409e82f736e53cd79393
1 ;;; -*- mode: lisp -*-
3 ;;; Time-stamp: <2009-03-21 09:30:48 tony>
4 ;;; Creation: <2008-09-08 08:06:30 tony>
5 ;;; File: listoflist.lisp
6 ;;; Author: AJ Rossini <blindglobe@gmail.com>
7 ;;; Copyright: (c) 2007-2008, AJ Rossini <blindglobe@gmail.com>. BSD.
8 ;;; Purpose: Manipulating structures which are lists of lists
9 ;;; rather than arrays or matrix-likes,
11 ;;; What is this talk of 'release'? Klingons do not make software
12 ;;; 'releases'. Our software 'escapes', leaving a bloody trail of
13 ;;; designers and quality assurance people in its wake.
16 ;; Where should this go?
17 (in-package :cls-data-listoflist)
20 ;; Glib commentary:
21 ;; Serious flaw -- need to consider that we are not really well
22 ;; working with the data structures, in that Luke created compound as
23 ;; a base class, which turns out to be slightly backward if we are to
24 ;; maintain the numerical structures as well as computational
25 ;; efficiency.
27 ;; Currently, we assume that the list-of-list representation is in
28 ;; row-major form, i.e. that lists represent rows and not columns.
29 ;; The original lisp-stat had the other way around. We could augment
30 ;; the top-level list with a property to check orientation
31 ;; (row-major/column-major), but this hasn't been done yet.
33 ;; This file contains code for going between listoflists,
34 ;; arrays/vectors, and matrix-like/vector-like data structures.
38 ;; Test cases:
39 (and T T nil T)
40 (and T T T)
41 (defparameter *x1* (list 1 2 3))
42 (defparameter *x2* (list 1 2 3))
43 (defparameter *x3* (list 1 2 3 4))
44 (defparameter *x4* (list 1 2 3))
45 (reduce #'(lambda (x y)
46 (if (= x y) y -1))
47 (mapcar #'length (list *x1* *x2* *x3*)))
48 (reduce #'(lambda (x y)
49 (if (= x y) y -1)) (list 2 3 2))
50 (lists-of-same-size *x1* *x2* *x4*) ; => T
51 (lists-of-same-size *x1* *x3* *x4*) ; => F
52 (lists-of-same-size *x1* *x2* *x3*) ; => F
53 (lists-of-same-size *x3* *x1* *x3*) ; => F
57 (defun lists-of-same-size (&rest list-of-list-names)
58 "Check if the lengths of the lists are equal (T, otherwise NIL), to
59 justify further processing and initial conditions."
60 (if (< 0 (reduce #'(lambda (x y) (if (= x y) y -1))
61 (mapcar #'length list-of-list-names)))
62 T nil))
65 ;; the following will be handy to help out folks adjust. It should
66 ;; provide a means to write code faster and better.
67 (defmacro make-dataframe-from-listoflist (datasetname
68 &optional (force-overwrite nil)
69 &rest lists-of-data-lists)
70 "Create a cases-by-variables data frame consisting of numeric data,
71 from a ROW-MAJOR list-of-lists representation. A COLUMN-MAJOR
72 representation should be handled using the transpose-listoflists
73 function."
74 (if (or (not (boundp datasetname))
75 force-overwrite)
76 (if (lists-of-same-size lists-of-data-lists)
77 `(defparameter ,datasetname
78 (make-matrix (length iron) 2
79 :initial-contents
80 (mapcar #'(lambda (x y)
81 (list (coerce x 'double-float)
82 (coerce y 'double-float)))
83 ,@lists-of-data-lists)))
84 (error "make-data-set-from-lists: no combining different length lists"))
85 (error "make-data-set-from-lists: proposed name exists")))
88 (macroexpand '(make-data-set-from-lists
89 this-data
90 :force-overwrite nil
91 aluminum iron))
92 (princ this-data)
95 (defun transpose-listoflist (listoflist)
96 "This function does the moral-equivalent of a matrix transpose on a
97 list-of-lists data structure"
98 (apply #'mapcar #'list listoflist))
100 ;; (defparameter LOL-2by3 (list (list 1 2) (list 3 4) (list 5 6)))
101 ;; (defparameter LOL-3by2 (list (list 1 3 5) (list 2 4 6)))
102 ;; (transpose-listoflists (transpose-listoflists LOL-2by3))
103 ;; (transpose-listoflists (transpose-listoflists LOL-3by2))
105 (defun equal-listoflist (x y)
106 "FIXME: This function, when written, should walk through 2 listoflists and
107 return T/nil based on equality."
108 (and (= (list-length x) ;; top-level length same
109 (list-length y))
110 ;; FIXME: within-level lengths same
111 ;; FIXME: flattened values same, walking through
112 ;; (loop over x and verify same tree as y)
116 (defun make-array-from-listoflist (lol) ; &key (type 'row-major)
117 "From a listoflists structure, make an array.
119 FIXME: need to verify that the listoflists is a valid structure (same
120 size rows, typing if required, etc.
122 <example>
123 (defparameter *mdfl-test*
124 (list (list 'a 1 2.1)
125 (list 'b 2 1.1)
126 (list 'c 1 2.0)
127 (list 'd 2 3.0)))
128 (length *mdfl-test*)
129 (length (elt *mdfl-test* 0))
131 (defparameter *mdfl-test-dt* (make-datatable-from-listoflists *mdfl-test*))
132 (array-dimensions *mdfl-test-dt*)
133 </example>"
134 (let ((n (length lol))
135 (p (length (elt lol 0))))
136 (let ((result (make-array (list n p))))
137 (dotimes (i n)
138 (dotimes (j p)
139 (setf (aref result i j) (elt (elt lol i) j))))
140 result)))
143 (defparameter *mdfl-test*
144 (list (list 'a 1 2.1)
145 (list 'b 2 1.1)
146 (list 'c 1 2.0)
147 (list 'd 2 3.0)))
148 (length *mdfl-test*)
149 (length (elt *mdfl-test* 0))
151 (defparameter *mdfl-test-dt* (make-datatable-from-listoflists *mdfl-test*))
152 (array-dimensions *mdfl-test-dt*)