Hi, I've started with this but got stuck at the plot. I'm trying to
print a simple plot with probably * as points (the val-x/val-y points
below) on a grid of 9 to 9 points. Not using CLOS or anything. Is it
possible? I only managed to print a lame version of the x and y axis.
;;Some values
(setf x (list 1 2 2 2 3 4 5 5 6 7 7 8 9 8 7 7 6 5 5))
(setf x (sort x #'<))
(defmacro unique (val lst)
`(setf ,val (remove-duplicates ,lst :test #'equal)))
;;Select bins as unique values
(unique bins x)
;;Define the empirical cumulative distribution:
(setf ecdf (loop for i in bins collect
(list i (/ (count i x :test #'>=) (length x) 1.0))))
;;The points with val-x and val-y coordinates
(setf val-x (mapcar #'car ecdf))
(setf val-y (mapcar #'cadr ecdf))
;;Lame attempt at a plot, still needs to add the points at the right
place in it:
(with-open-file (str "c:/lispGraph.doc" :direction :output)
(format str "~{~a~%~%~%~}" (loop for i from 9 downto 1 collect i))
(format str "~{~a ~}" (loop for i from 0 to 9 collect i)))
On Sun, 26 Apr 2009 14:43:06 -0700, Francogrex wrote:
> Hi, I've started with this but got stuck at the plot. I'm trying to
> print a simple plot with probably * as points (the val-x/val-y points
> below) on a grid of 9 to 9 points. Not using CLOS or anything. Is it
> possible? I only managed to print a lame version of the x and y axis.
>
> ;;Some values
> (setf x (list 1 2 2 2 3 4 5 5 6 7 7 8 9 8 7 7 6 5 5)) (setf x (sort x
> #'<))
>
> (defmacro unique (val lst)
> `(setf ,val (remove-duplicates ,lst :test #'equal)))
>
> ;;Select bins as unique values
> (unique bins x)
>
> ;;Define the empirical cumulative distribution: (setf ecdf (loop for i
> in bins collect
> (list i (/ (count i x :test #'>=) (length x) 1.0))))
>
> ;;The points with val-x and val-y coordinates (setf val-x (mapcar #'car
> ecdf))
> (setf val-y (mapcar #'cadr ecdf))
>
> ;;Lame attempt at a plot, still needs to add the points at the right
> place in it:
> (with-open-file (str "c:/lispGraph.doc" :direction :output)
> (format str "~{~a~%~%~%~}" (loop for i from 9 downto 1 collect i))
> (format str "~{~a ~}" (loop for i from 0 to 9 collect i)))
I rewrote it in a more lispy style, and put some comments in it.
Hopefully pan (my newsreader) will not screw up the formatting.
;;Some values TP: use defparameter, not setf
(defparameter *x* (list 1 2 2 2 3 4 5 5 6 7 7 8 9 8 7 7 6 5 5))
(setf *x* (sort *x* #'<))
(let* (;;Select bins as unique values TP: macro unnecessary, was bad style
(bins (remove-duplicates *x* :test #'equal))
;; define the empirical cumulative distribution
;; TP: pointless to save bins again, you already have them
(ecdf (loop for i in bins collect
(/ (count i *x* :test #'>=) (length *x*) 1.0)))
(width 40) ; width of largest column
(scale (/ width (apply #'max ecdf))))
;; plot, not sure what you want to do
(with-open-file (str "/tmp/plot" :direction :output)
(mapc #'(lambda (bin prob) ; yes, I hate loop :-)
(format str "~2d " bin)
(dotimes (i (round (* prob scale))) ; we scale to the screen
(princ #\* str)) ; points
(terpri str)) ; newline
bins ecdf)))
Tamas
> Hi, I've started with this but got stuck at the plot. I'm trying to
> print a simple plot with probably * as points (the val-x/val-y points
> below) on a grid of 9 to 9 points.
So you have grids of points.
(defstruct grid points)
and you want to plot points:
(defun plot (grid x y &optional (point '*))
...)
and you will probably want to display this grid once you've ploted the points:
(defun display (grid)
...)
Ok, how could we do that? You say the grid has points with 2
coordinates. We could use a 2D array of characters to store them.
(defstruct (grid (:constructor %make-grid)) points)
(defun make-grid (width height &optional (initial-point #\space))
(%make-grid :points (make-array (list width height)
:element-type 'character
:initial-element initial-point)))
Now you can plot in that:
(defun plot (grid x y &optional (point '*))
(setf (aref (grid-points grid) (round x) (round y)) (character (string point)))
grid)
and you can easily display it:
(defun display (grid)
(loop
:for y :from 0 :below (array-dimension (grid-points grid) 1)
:do (loop
:for x :from 0 :below (array-dimension (grid-points grid) 0)
:do (princ (aref (grid-points grid) x y))
:finally (terpri)))
grid)
(let ((grid (make-grid 72 24)))
(loop :for x :from 0 :below 72 :do (plot grid x 12 '-))
(loop :for x :from 0 :below 72 :do (plot grid x (+ 12 (* 9 (sin (* 2 pi (/ x 72))))) '+))
(display grid)
(values))
+++++++
+++ +++
++ ++
++ ++
+ +
++ ++
+ +
++ ++
+ +
+-----------------------------------+-----------------------------------
+ +
++ ++
+ +
++ ++
+ +
++ ++
++ ++
+++ +++
+++++++
--
__Pascal Bourguignon__