API cleanup,
[CommonLispStat.git] / src / data / listoflist.lisp
blobbb8aed1612f04c051ce64f3f0efd99396e8f4a40
1 ;;; -*- mode: lisp -*-
3 ;;; Time-stamp: <2009-04-11 19:01:27 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 (defun listoflist->array (lol &key (type 'row-major))
66 "From a listoflists structure, make an array.
68 FIXME: need to verify that the listoflists is a valid structure (same
69 size rows, typing if required, etc.
71 <example>
72 (defparameter *mdfl-test*
73 (list (list 'a 1 2.1)
74 (list 'b 2 1.1)
75 (list 'c 1 2.0)
76 (list 'd 2 3.0)))
77 (length *mdfl-test*)
78 (length (elt *mdfl-test* 0))
80 (defparameter *mdfl-test-dt* (make-datatable-from-listoflists *mdfl-test*))
81 (array-dimensions *mdfl-test-dt*)
82 </example>"
83 (let ((n (length lol))
84 (p (length (elt lol 0))))
85 (let ((result (make-array (list n p))))
86 (dotimes (i n)
87 (dotimes (j p)
88 (if (equal type :row-major)
89 (setf (aref result i j) (elt (elt lol i) j))
90 (setf (aref result i j) (elt (elt lol j) i)))))
91 result)))
94 ;; the following will be handy to help out folks adjust. It should
95 ;; provide a means to write code faster and better.
96 (defun listoflist->dataframe (lol) ; &key (type :row-major))
97 "Create a cases-by-variables data frame consisting of numeric data,
98 from a ROW-MAJOR list-of-lists representation. A COLUMN-MAJOR
99 representation should be handled using the transpose-listoflists
100 function."
101 (if (lists-of-same-size lol)
102 (make-dataframe (listoflist->array lol))
103 (error "make-data-set-from-lists: no combining different length lists"))
104 (error "make-data-set-from-lists: proposed name exists"))
107 (defun transpose-listoflist (listoflist)
108 "This function does the moral-equivalent of a matrix transpose on a
109 list-of-lists data structure"
110 (apply #'mapcar #'list listoflist))
112 ;; (defparameter LOL-2by3 (list (list 1 2) (list 3 4) (list 5 6)))
113 ;; (defparameter LOL-3by2 (list (list 1 3 5) (list 2 4 6)))
114 ;; (transpose-listoflists (transpose-listoflists LOL-2by3))
115 ;; (transpose-listoflists (transpose-listoflists LOL-3by2))
117 (defun equal-listoflist (x y)
118 "FIXME: This function, when written, should walk through 2 listoflists and
119 return T/nil based on equality."
120 (and (= (list-length x) ;; top-level length same
121 (list-length y))
122 ;; FIXME: within-level lengths same
123 ;; FIXME: flattened values same, walking through
124 ;; (loop over x and verify same tree as y)
130 (defparameter *mdfl-test*
131 (list (list 'a 1 2.1)
132 (list 'b 2 1.1)
133 (list 'c 1 2.0)
134 (list 'd 2 3.0)))
135 (length *mdfl-test*)
136 (length (elt *mdfl-test* 0))
138 (defparameter *mdfl-test-dt* (make-datatable-from-listoflists *mdfl-test*))
139 (array-dimensions *mdfl-test-dt*)