Uh oh!
There was an error while loading. Please reload this page.
This repository was archived by the owner on Jul 5, 2026. It is now read-only.
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgg.lisp
More file actions
Latest commit
109 lines (95 loc) · 4.48 KB
/
Copy pathgg.lisp
File metadata and controls
109 lines (95 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
;;; -*- Mode: LISP; Syntax: Ansi-Common-Lisp; Base: 10; Package: GG -*-
;;; Copyright (c) 2026 Symbolics Pte. Ltd. All rights reserved.
;;; Geometry helpers for common Vega-Lite plot types.
(in-package#:gg)
(defunlabel (&key x y) ;'labels' is a CL keyword
"Return a plist with axis title encodings, suitable for merging.
Sets the :title property directly on each encoding channel rather than
nesting inside :axis, so that composite marks like boxplot (which
expand into multiple sub-layers) resolve a single authoritative title
instead of concatenating the field name with per-layer axis titles."
`(,@(when (or x y)
`(:encoding (,@(when x `(:x (:title,x)))
,@(when y `(:y (:title,y))))))))
(defunaxes (&key x-type y-type
x-domain y-domain
x-range y-range
color-scheme)
"Return a plist with scale encodings, suitable for merging.
X-TYPE/Y-TYPE: :log :sqrt :time etc.
X-DOMAIN/Y-DOMAIN: explicit (min max) domain list
X-RANGE/Y-RANGE: explicit (min max) range list
COLOR-SCHEME: a Vega scheme name e.g. :category10 :viridis"
`(,@(when (or x-type x-domain x-range)
`(:encoding (:x (:scale (,@(when x-type `(:type,x-type))
,@(when x-domain `(:domain,x-domain))
,@(when x-range `(:range,x-range)))))))
,@(when (or y-type y-domain y-range)
`(:encoding (:y (:scale (,@(when y-type `(:type,y-type))
,@(when y-domain `(:domain,y-domain))
,@(when y-range `(:range,y-range)))))))
,@(when color-scheme
`(:encoding (:color (:scale (:scheme,color-scheme)))))))
(defuntooltip (&rest fields)
"Return encoding plist adding tooltip channels.
Each field is one of:
:keyword — nominal field (shorthand)
(:keyword :type) — field with explicit type, e.g. (:horsepower :quantitative)
(:field f :type t) — full Vega-Lite channel plist (passed through)
The result uses a vector so the serializer emits a JSON array."
(let ((channels (mapcar (lambda (f)
(cond ((keywordp f)
`(:field,f :type:nominal))
((and (listp f)
(= (length f) 2)
(keywordp (first f))
(keywordp (second f)))
`(:field,(first f) :type,(second f)))
((listp f) f)
(t`(:field,f :type:nominal))))
fields)))
`(:encoding (:tooltip,(coerce channels 'vector)))))
(defuncoord (&key x-domain y-domain (clip t))
"Return plist clamping axis domains and optionally clipping marks.
Like ggplot2's coord_cartesian: restricts the visible area without
dropping data.
X-DOMAIN / Y-DOMAIN:
- For quantitative axes: a vector #(min max)
- For categorical axes: a vector of category names #(\"A\"\"B\"\"C\")
CLIP: if T (default), marks outside the domain are hidden.
Set to NIL for bar/boxplot where clipping cuts marks."
`(,@(when clip `(:mark (:clipt)))
,@(when x-domain
`(:encoding (:x (:scale (:domain,x-domain)))))
,@(when y-domain
`(:encoding (:y (:scale (:domain,y-domain)))))))
(defuntheme (&key width height font background
(view-stroke :null)
padding)
"Return plist for layout and theme settings.
WIDTH, HEIGHT: pixel dimensions
FONT: base font family string — applied to the entire chart via config.font
BACKGROUND: CSS color string for the chart background
VIEW-STROKE: stroke around the view rectangle; :null (default) removes it, a string sets a CSS color, NIL omits the property entirely
PADDING: padding in pixels (number) or plist (:left :right :top :bottom)
Like ggplot2's coord_cartesian: restricts the visible area without
dropping data.
X-DOMAIN / Y-DOMAIN:
- For quantitative axes: a vector #(min max)
- For categorical axes: a vector of category names #(\"A\"\"B\"\"C\")
CLIP: if T (default), marks outside the domain are hidden.
Set to NIL for bar/boxplot where clipping cuts marks."
(let ((config-props `(,@(when font `(:font,font))
,@(unless (null view-stroke)
`(:view (:stroke,view-stroke))))))
`(,@(when width `(:width,width))
,@(when height `(:height,height))
,@(when background `(:background,background))
,@(when padding `(:padding,padding))
,@(when config-props `(:config,config-props)))))
(defunlayer (&rest geom-plists)
"Wrap two or more geom plists into a Vega-Lite layer spec. Each argument should be the plist returned by a geom:* function.
EXAMPLE
(gg:layer (geom:line :date :price :x-type :temporal)
(geom:error-bar :price :category :date :extent :ci))"
`(:layer,(apply#'vector geom-plists)))