Wiki
Download
Manual
Eggs
API
Tests
Bugs
show
edit
history
You can edit this page using
wiki syntax
for markup.
Article contents:
[[tags: egg graphics plot]] [[toc:]] == gg-plot A declarative plotting system built on top of the Cairo graphics library which provides ggplot2-style plotting routines, with s-expression plot specifications, automatic scale training, and four output formats (PNG, SVG, PostScript, PDF). === Requirements * [[/eggref/5/cairo|cairo]] (Cairo graphics bindings) * [[/eggref/5/matchable|matchable]] * [[/eggref/5/datatype|datatype]] * [[/eggref/5/yasos|yasos]] * [[/eggref/5/statistics|statistics]] === Overview The library is organised into nine modules that correspond to the tiers of the Grammar of Graphics. Most users only need to {{(import gg-plot)}}; the lower-level modules are available for custom rendering pipelines. ; {{gg-plot}}: Full declarative plot API ; {{gg-vge}}: Virtual Graphics Engine — algebraic IR for graphics instructions ; {{gg-backend}}: Abstract backend protocol (YASOS interface) ; {{gg-backend-cairo}}: Cairo backend; PNG, SVG, PostScript, and PDF output ; {{gg-primitives-vge}}: Composable drawer abstraction; shapes, text, transforms ; {{gg-scales}}: Data-to-visual mappings (linear, log, ordinal, color) ; {{gg-data}}: Columnar data utilities ; {{gg-aes}}: Aesthetic (column-channel) mapping ; {{gg-geom}}: Geometry functions (scatter, line, bar, errorbar, raster...) ; {{gg-guides}}: Axis and legend drawers === The translation pipeline <enscript> s-expression spec -> normalize / validate defaults -> train scales from all layers -> compute facet panels -> render each panel (background, geometries, axes) -> render global elements (title, legends) -> emit via Cairo (PNG / SVG / PS / PDF) </enscript> == Module: gg-plot The top-level declarative API. Import only this module for typical use. <enscript highlight="scheme"> (import gg-plot) </enscript> === Plot construction <procedure>(ggplot data . specs)</procedure> Create a {{plot-spec}} record. ''data'' is a columnar alist. ''specs'' is a mixed list of: * an {{(aes ...)}} call for the default aesthetic mapping, * layer constructors ({{layer-point}}, {{layer-line}}, …), * scale specifications ({{scale-x-continuous}}, …), * a coordinate system ({{coord-cartesian}}, …), * a faceting specification ({{facet-wrap}}, {{facet-grid}}), * a theme ({{theme-minimal}}, …), * {{(labs ...)}} for title and axis labels. <enscript highlight="scheme"> (define p (ggplot data (aes #:x 'time #:y 'value #:color 'condition) (layer-line #:width 2) (layer-point #:size 5) (scale-x-continuous #:name "Time (ms)") (scale-y-continuous #:name "Response (mV)") (scale-color-manual #:values '(("Control" . "blue") ("Treatment" . "red"))) (theme-minimal #:base-size 12) (labs #:title "Treatment vs Control"))) </enscript> === Rendering <procedure>(render-plot plot-spec backend)</procedure> Execute the full rendering pipeline and write output. ''backend'' is a Cairo backend constructed with one of the {{make-cairo-*-backend}} procedures from {{gg-backend-cairo}}. <procedure>(ggsave plot-spec filename #!key width height format scale)</procedure> Save to a file. ''format'' is inferred from the extension ({{.png}}, {{.svg}}, {{.ps}}) or can be given explicitly as {{'png}}, {{'svg}}, or {{'ps}}. ''width''/''height'' default to 800×600. <procedure>(ggdisplay plot-spec #!key width height)</procedure> Render to an X11 window. === Plot serialisation <procedure>(plot->sexp plot-spec)</procedure> Convert a plot specification to a pure s-expression (no closures). The result can be written to a file with {{write}} and read back later. <procedure>(sexp->plot sexp)</procedure> Reconstruct a {{plot-spec}} from a serialised s-expression. === Layer constructors All layer constructors accept {{#:data}} (override dataset), {{#:mapping}} (override or extend the plot-level aesthetic mapping), plus geometry-specific keyword arguments. ==== Basic geometries <procedure>(layer-point #!key data mapping size shape alpha color)</procedure> <procedure>(layer-line #!key data mapping width style color)</procedure> <procedure>(layer-path #!key data mapping width color)</procedure> <procedure>(layer-area #!key data mapping fill alpha)</procedure> <procedure>(layer-bar #!key data mapping fill width)</procedure> <procedure>(layer-rect #!key data mapping fill color)</procedure> <procedure>(layer-text #!key data mapping size color)</procedure> <procedure>(layer-segment #!key data mapping color width)</procedure> <procedure>(layer-eventplot #!key data mapping line-length width color)</procedure> ==== Reference lines <procedure>(layer-hline yintercept #!key color width linetype alpha)</procedure> <procedure>(layer-vline xintercept #!key color width linetype alpha)</procedure> ''linetype'' is {{'solid}}, {{'dashed}}, or {{'dotted}}. ==== Statistical geometry layers <procedure>(layer-histogram #!key data mapping bins binwidth breaks method fill color alpha)</procedure> ; {{bins}} : number of bins (default 30) ; {{binwidth}} : bin width in data units (overrides {{bins}}) ; {{method}} : {{'sturges}} (default), {{'scott}}, {{'fd}}, {{'equal-width}} <procedure>(layer-density #!key data mapping bandwidth kernel n adjust fill color alpha)</procedure> ; {{kernel}} : {{'gaussian}} (default), {{'epanechnikov}}, {{'rectangular}}, {{'triangular}}, {{'biweight}} ; {{n}} : number of evaluation points (default 512) <procedure>(layer-boxplot #!key data mapping coef varwidth fill color outlier-color outlier-size width)</procedure> ; {{coef}} : IQR multiplier for whisker length (default 1.5) <procedure>(layer-violin #!key data mapping scale draw-quantiles bandwidth kernel fill color alpha)</procedure> ; {{scale}} : {{'area}} (equal area, default) or {{'count}} (proportional to n) ; {{draw-quantiles}} : list of quantile levels, e.g. {{'(0.25 0.5 0.75)}} <procedure>(layer-errorbar #!key data mapping stat fun-ymin fun-ymax color width cap-width)</procedure> ; {{stat}} : {{'identity}} (use {{ymin}}/{{ymax}} columns) or {{'summary}} (compute from raw values) <procedure>(layer-pointrange #!key data mapping stat fun-y fun-ymin fun-ymax color point-size line-width)</procedure> <procedure>(layer-linerange #!key data mapping stat fun-ymin fun-ymax color width)</procedure> <procedure>(layer-crossbar #!key data mapping stat fun-y fun-ymin fun-ymax fill color width)</procedure> <procedure>(layer-col #!key data mapping fun position fill color width)</procedure> ; {{position}} : {{'stack}} (default), {{'dodge}}, {{'fill}} ==== Annotation layers <procedure>(layer-annotate-text text x y #!key size color hjust vjust angle)</procedure> <procedure>(layer-annotate-rect xmin ymin xmax ymax #!key fill alpha color line-width)</procedure> <procedure>(layer-annotate-segment x1 y1 x2 y2 #!key color width)</procedure> <procedure>(layer-annotate-arrow x1 y1 x2 y2 #!key color width)</procedure> Coordinates are in data space. For reference lines with full linetype support, the following are recommended over {{layer-hline}}/{{layer-vline}} when annotation-layer dispatch is needed: <procedure>(annotate-vline x #!key color width linetype)</procedure> <procedure>(annotate-hline y #!key color width linetype)</procedure> <procedure>(annotate-abline slope intercept #!key color width)</procedure> === Scale specifications Scale specification functions return tagged lists consumed by {{ggplot}}. ==== Continuous position scales <procedure>(scale-x-continuous #!key name limits breaks trans expand)</procedure> <procedure>(scale-y-continuous #!key name limits breaks trans expand)</procedure> ; {{name}} : axis title string ; {{limits}} : explicit domain {{(min max)}} ; {{breaks}} : explicit tick positions ; {{trans}} : transformation symbol: {{'log}}, {{'log10}}, {{'sqrt}}, … ; {{expand}} : fractional padding added to domain on each side <procedure>(scale-x-log #!key name base breaks)</procedure> <procedure>(scale-y-log #!key name base breaks)</procedure> Shorthand for a continuous scale with {{trans: 'log}} and the given ''base'' (default 10). ==== Discrete position scales <procedure>(scale-x-discrete #!key name limits)</procedure> <procedure>(scale-y-discrete #!key name limits)</procedure> === Color / fill scales <procedure>(scale-color-manual #!key values)</procedure> <procedure>(scale-fill-manual #!key values)</procedure> ''values'' is an alist: {{'(("Control" . "blue") ("Treatment" . "red"))}}. <procedure>(scale-color-gradient #!key low high limits)</procedure> Two-stop continuous gradient. === Coordinate systems <procedure>(coord-cartesian #!key xlim ylim)</procedure> Default Cartesian coordinates with optional axis limits. <procedure>(coord-fixed #!key ratio xlim ylim)</procedure> Fixed aspect ratio (default 1:1). <procedure>(coord-flip)</procedure> Swap x and y axes. === Faceting <procedure>(facet-null)</procedure> No faceting (single panel, default). <procedure>(facet-wrap var #!key ncol nrow scales)</procedure> Wrap panels by ''var'' (a quoted symbol). {{scales}} is one of {{"fixed"}} (default), {{"free"}}, {{"free_x"}}, {{"free_y"}}. <procedure>(facet-grid row-var col-var #!key scales space shrink labeller)</procedure> Two-dimensional panel grid. Pass {{#f}} for either variable to omit that dimension. === Themes <procedure>(theme-gray #!key base-size base-family)</procedure> Gray background with white grid lines (the default ggplot2-style theme). <procedure>(theme-minimal #!key base-size base-family)</procedure> White background, no border, gray grid lines. ''base-size'' defaults to 11. <procedure>(theme-classic #!key base-size base-family)</procedure> White background, no grid lines, axis lines present. <procedure>(theme-bw #!key base-size)</procedure> White background, black border, gray grid lines. <procedure>(theme-linedraw #!key base-size base-family)</procedure> White background, black grid lines and border. <procedure>(theme-light #!key base-size base-family)</procedure> Light gray border and grid lines. <procedure>(theme-dark #!key base-size base-family)</procedure> Dark background with contrasting grid lines; suitable for bright-colored data. <procedure>(theme-void #!key base-size)</procedure> No background, no axes, no grid. ==== Legend position modifiers <procedure>(theme-legend-position position)</procedure> ''position'': {{'right}} (default), {{'left}}, {{'top}}, {{'bottom}}, {{'none}}, {{'inside}}, {{'outside}}. <procedure>(theme-legend-inside position)</procedure> ''position'': {{'top-right}}, {{'top-left}}, {{'bottom-right}}, {{'bottom-left}}, {{'center}}. <procedure>(theme-legend-outside position)</procedure> ''position'': {{'right}}, {{'left}}, {{'top}}, {{'bottom}}. === Labels <procedure>(labs #!key title subtitle x y caption)</procedure> <procedure>(xlab name)</procedure> <procedure>(ylab name)</procedure> <procedure>(ggtitle title [subtitle])</procedure> ==== Collision-avoiding text <procedure>(geom-text-repel ...)</procedure> <procedure>(geom-label-repel ...)</procedure> Repel overlapping text labels using a force-directed algorithm. Accepts the same arguments as {{layer-text}}. === Plot-spec accessors <procedure>(plot-spec? obj)</procedure> <procedure>(plot-spec-data spec)</procedure> <procedure>(plot-spec-default-aes spec)</procedure> <procedure>(plot-spec-layers spec)</procedure> <procedure>(plot-spec-scales spec)</procedure> <procedure>(plot-spec-coord spec)</procedure> <procedure>(plot-spec-facet spec)</procedure> <procedure>(plot-spec-theme spec)</procedure> <procedure>(plot-spec-labels spec)</procedure> == Module: gg-primitives-vge Low-level composable drawing layer. A ''drawer'' is a record wrapping a procedure that emits instructions into a VGE (Virtual Graphics Engine). Drawers are first-class values: they can be stored, composed with {{combine}}, and wrapped with style or transform combinators before being rendered to any backend. Coordinate convention: right-handed, origin at bottom-left, Y-up. All coordinates are in user space; the backend maps them to device pixels. === Drawer record <procedure>(make-drawer proc bounds)</procedure> Create a drawer from a procedure {{(vge -> void)}} and an optional bounding box (or {{#f}}). <procedure>(drawer? obj)</procedure> True if ''obj'' is a drawer record. <procedure>(drawer-proc drawer)</procedure> <procedure>(drawer-bounds drawer)</procedure> Accessors. <procedure>empty-drawer</procedure> A drawer that does nothing (identity for {{combine}}). === Composition <procedure>(combine drawer ...)</procedure> Return a new drawer that executes each argument drawer left-to-right with no additional scoping. <procedure>(combine-group drawer ...)</procedure> Like {{combine}} but wraps the result in a {{gfx:group}} scope. === Rendering <procedure>(render-drawer drawer vge)</procedure> Emit a drawer's instructions into ''vge'' (a VGE accumulator created by {{make-vge}} from {{gg-vge}}). Does not perform I/O; call {{vge-render!}} afterwards to send the instructions to a backend. === Scoped state wrappers Each wrapper produces a {{gfx:group}}, so the state change is automatically scoped; no explicit push/pop is needed. <procedure>(with-pushed-state drawer)</procedure> Raw push/pop scope (low-level; prefer the typed wrappers below). <procedure>(with-translate dx dy drawer)</procedure> <procedure>(with-viewport x0 y0 x1 y1 drawer)</procedure> <procedure>(with-clip-rect x y w h drawer)</procedure> <procedure>(with-rotate angle drawer)</procedure> ''angle'' in radians. === Style wrappers <procedure>(with-pen-color color drawer)</procedure> ''color'' is a color string ({{"steelblue"}}, {{"#3f7ab5"}}) or a {{color:rgba}} / {{color:named}} value from {{gg-backend}}. <procedure>(with-fill-color color drawer)</procedure> <procedure>(with-line-width width drawer)</procedure> ''width'' in user coordinates. <procedure>(with-dash dashes offset drawer)</procedure> ''dashes'' is a list of on/off lengths; ''offset'' is the phase. <procedure>(with-font family size slant weight drawer)</procedure> ''family'' is a font family string (e.g. {{"sans-serif"}}); ''slant'' is {{'normal}} or {{'italic}}; ''weight'' is {{'normal}} or {{'bold}}. === Stroked drawing primitives <procedure>(line-drawer x1 y1 x2 y2)</procedure> <procedure>(polyline-drawer pts)</procedure> ''pts'' is a list of {{(x . y)}} pairs. <procedure>(rect-drawer x y w h)</procedure> Outline rectangle; bottom-left corner at (''x'', ''y''). <procedure>(circle-drawer cx cy r)</procedure> <procedure>(polygon-drawer pts)</procedure> === Filled drawing primitives <procedure>(filled-rect-drawer x y w h)</procedure> <procedure>(filled-circle-drawer cx cy r)</procedure> <procedure>(filled-polygon-drawer pts)</procedure> === Text <procedure>(text-drawer x y text #!key halign valign)</procedure> Draw ''text'' anchored at (''x'', ''y''). ; {{halign}} : {{'left}}, {{'center}} (default), or {{'right}} ; {{valign}} : {{'top}}, {{'center}}, {{'bottom}}, or {{'baseline}} (default) === Convenience drawers <procedure>(h-line-drawer x1 x2 y)</procedure> <procedure>(v-line-drawer x y1 y2)</procedure> <procedure>(filled-rect+border-drawer x y w h fill-color edge-color)</procedure> <procedure>(path-drawer cmds #!key filled?)</procedure> ''cmds'' is a list of path commands from {{gg-backend}}: {{path:move-to}}, {{path:line-to}}, {{path:curve-to}}, {{path:arc}}, {{path:close}}. ---- == Module: gg-backend-cairo Cairo graphics backend. Implements the abstract backend protocol from {{gg-backend}} for four output formats. <procedure>(make-cairo-png-backend filename width height)</procedure> PNG raster output. ''width'' and ''height'' are in pixels. <procedure>(make-cairo-svg-backend filename width height)</procedure> SVG vector output. <procedure>(make-cairo-ps-backend filename width height)</procedure> PostScript output. <procedure>(make-cairo-pdf-backend filename width height)</procedure> PDF output. ''width'' and ''height'' are in points (72 pt = 1 inch; A4 portrait = 595 × 842 pt). ---- == Module: gg-scales Scales map between the data domain and the visual range. All scale objects implement the same protocol (via YASOS), so geometry and guide code is scale-type–agnostic. === Scale protocol <procedure>(scale? obj)</procedure> <procedure>(scale-type scale)</procedure> Returns a symbol: {{'linear}}, {{'log}}, {{'sqrt}}, {{'power}}, {{'ordinal}}, {{'band}}, {{'color-gradient}}, {{'color-manual}}, … <procedure>(scale-train! scale values)</procedure> Extend the domain to include ''values'' (a list). Mutates the scale. <procedure>(scale-map scale value)</procedure> Map a single domain value to the visual range. <procedure>(scale-inverse scale value)</procedure> Map from visual range back to domain. <procedure>(scale-breaks scale [n])</procedure> Return a list of ''n'' (default 5) nicely-placed tick positions. <procedure>(scale-labels scale breaks)</procedure> Return formatted label strings for the given break positions. <procedure>(scale-domain scale)</procedure> Current domain as a {{(min . max)}} pair, or a list for discrete scales. <procedure>(scale-range scale)</procedure> Current visual range as a {{(min . max)}} pair. <procedure>(scale-set-domain! scale domain)</procedure> <procedure>(scale-set-range! scale range)</procedure> Mutating setters. <procedure>(scale-bandwidth scale)</procedure> Width of a single band (for band scales only). === Functional scale combinators These return a new scale and leave the original unmodified. <procedure>(scale-with-domain scale domain)</procedure> <procedure>(scale-with-range scale range)</procedure> <procedure>(scale-with-trained scale values)</procedure> <procedure>(scale-with-transform scale transform-type)</procedure> ''transform-type'' is one of: {{'log}}, {{'log10}}, {{'log2}}, {{'ln}}, {{'sqrt}}, {{'identity}}. <procedure>(scale-with-breaks scale explicit-breaks)</procedure> Override automatic break computation with a fixed list. === Continuous scale constructors <procedure>(make-scale-linear #!key domain range)</procedure> <procedure>(make-scale-log #!key domain range base)</procedure> ''base'' defaults to 10. <procedure>(make-scale-sqrt #!key domain range)</procedure> <procedure>(make-scale-power #!key domain range exponent)</procedure> ''exponent'' defaults to 2. === Discrete scale constructors <procedure>(make-scale-ordinal #!key domain range)</procedure> Maps each domain value to the corresponding entry in ''range'', cycling if necessary. <procedure>(make-scale-band #!key domain range padding)</procedure> Like ordinal but maps to a continuous sub-interval (band) for bar charts. ''padding'' (default 0.1) is the fraction of each step reserved for spacing. === Color scale constructors <procedure>(make-scale-color-gradient #!key domain low high)</procedure> Continuous gradient interpolating between ''low'' and ''high'' color strings. Accepts named colors ({{"blue"}}) and hex strings ({{"#3f7ab5"}}). <procedure>(make-scale-color-diverging #!key domain low mid high midpoint)</procedure> Two-segment gradient with a midpoint color. <procedure>(make-scale-color-ordinal #!key domain palette)</procedure> Ordinal scale backed by a list of color strings. <procedure>(make-scale-color-manual value-map)</procedure> Explicit category -> color alist, e.g. {{`(("Control" . "blue") ("Treatment" . "red"))}} === Break utilities <procedure>(nice-breaks min-val max-val n)</procedure> <procedure>(compute-pretty-breaks min max n)</procedure> <procedure>(extend-domain domain expansion)</procedure> Extend ''domain'' by the fractional ''expansion'' on each side (e.g. 0.05 adds 5 % padding). == Module: gg-data Columnar data frames: an association list mapping column names (symbols) to parallel value lists. <enscript highlight="scheme"> (define data '((time . (0 10 20 30 40 50)) (value . (1.2 1.5 2.3 1.8 1.4 1.9)) (group . ("A" "A" "A" "B" "B" "B")))) </enscript> <procedure>(data-column data column-name)</procedure> Extract a column list. Signals an error if the column is absent. <procedure>(data-columns data)</procedure> List of column name symbols. <procedure>(data-n-rows data)</procedure> <procedure>(data-row data index)</procedure> Single row as an association list {{((col . value) ...)}}. <procedure>(data-rows data)</procedure> All rows as a list of association lists. Used internally by geometries. <procedure>(columns->rows data)</procedure> <procedure>(rows->columns rows)</procedure> Convert between the columnar and row-oriented representations. == Module: gg-aes Aesthetic mappings link data columns to visual channels. === Creating mappings <procedure>(aes #!key x y color fill size shape alpha linetype group label)</procedure> <procedure>(make-aes ...)</procedure> Both are equivalent. Column references are symbols; literal values are strings or numbers: <enscript highlight="scheme"> (aes #:x 'time #:y 'value #:color 'condition) ; x, y, color mapped to columns (aes #:x 'time #:y 'value #:color "steelblue") ; color is a constant </enscript> <procedure>(aesthetic-mapping? obj)</procedure> === Accessors <procedure>(aes-x mapping)</procedure> <procedure>(aes-y mapping)</procedure> <procedure>(aes-color mapping)</procedure> <procedure>(aes-fill mapping)</procedure> <procedure>(aes-size mapping)</procedure> <procedure>(aes-shape mapping)</procedure> <procedure>(aes-alpha mapping)</procedure> <procedure>(aes-linetype mapping)</procedure> <procedure>(aes-group mapping)</procedure> <procedure>(aes-label mapping)</procedure> <procedure>(aes-get mapping key [default])</procedure> === Utilities <procedure>(aes-merge base override)</procedure> Merge two mappings; ''override'' wins on conflicts. <procedure>(aes-has? mapping key)</procedure> <procedure>(aes-keys mapping)</procedure> <procedure>(aes-map-value mapping key data-row)</procedure> Resolve an aesthetic: if the stored value is a symbol, look it up in ''data-row'' (an association list); otherwise return the literal value. <procedure>(constant-value? value)</procedure> <procedure>(mapped-value? value)</procedure> ---- == Module: gg-geom Geometry functions take a columnar data frame and an aesthetic mapping and return {{(values drawer trained-scales)}}. They are normally used indirectly through the layer constructors in {{gg-plot}}, but can be called directly for custom pipelines. === Core geometries <procedure>(geom-point data aes #!key scales size shape alpha)</procedure> Scatter plot. Required aesthetics: {{x}}, {{y}}. Optional: {{color}}, {{fill}}, {{size}}. <procedure>(geom-line data aes #!key scales width style)</procedure> Line plot. Groups rows by the {{color}} or {{group}} aesthetic and draws a separate polyline per group. Required: {{x}}, {{y}}. <procedure>(geom-path data aes #!key scales width color)</procedure> Like {{geom-line}} but connects points in data order without sorting. <procedure>(geom-area data aes #!key scales fill alpha)</procedure> Filled area. With only {{x}}/{{y}} aesthetics, fills from 0 to ''y'' (simple area). With {{ymin}}/{{ymax}} aesthetics, fills between the two curves (ribbon). <procedure>(geom-bar data aes #!key scales fill width)</procedure> Bar chart. Required: {{x}}, {{y}}. <procedure>(geom-rect data aes #!key scales)</procedure> Draws rectangles from {{xmin}}/{{xmax}}/{{ymin}}/{{ymax}} aesthetics. <procedure>(geom-text data aes #!key scales size color)</procedure> Text labels positioned at {{x}}/{{y}}, string from {{label}} aesthetic. <procedure>(geom-segment data aes #!key scales color width)</procedure> Line segments from ({{x}}, {{y}}) to ({{xend}}, {{yend}}). <procedure>(geom-hline data aes #!key scales color width linetype)</procedure> <procedure>(geom-vline data aes #!key scales color width linetype)</procedure> Reference lines. === Event plot <procedure>(geom-eventplot data aes #!key scales line-length width color)</procedure> Draws one vertical tick per event time. Expects {{x}} to hold a ''list of timestamps'' per row and {{y}} to hold the row index (trial number). <enscript highlight="scheme"> (define spike-data '((trial . (0 1 2 3 4)) (spikes . ((12 25 38) (15 28 42) (10 23 40) (18 30 45) (13 27 41))))) (geom-eventplot spike-data (aes #:x 'spikes #:y 'trial) #:line-length 0.7 #:width 1 #:color "black") </enscript> === Statistical geometries <procedure>(geom-histogram data aes #!key scales bins fill color alpha)</procedure> <procedure>(geom-density data aes #!key scales fill color alpha)</procedure> <procedure>(geom-boxplot data aes #!key scales fill color width)</procedure> <procedure>(geom-violin data aes #!key scales fill color alpha)</procedure> <procedure>(geom-errorbar data aes #!key scales color width cap-width)</procedure> <procedure>(geom-crossbar data aes #!key scales fill color width)</procedure> <procedure>(geom-linerange data aes #!key scales color width)</procedure> <procedure>(geom-pointrange data aes #!key scales color point-size line-width)</procedure> == Module: gg-guides Axis and legend rendering. Returns drawers positioned in axis-local coordinates; {{gg-plot}} translates them to panel coordinates. === Axes <procedure>(make-axis-bottom scale #!key label tick-count)</procedure> <procedure>(make-axis-top scale #!key label tick-count)</procedure> <procedure>(make-axis-left scale #!key label tick-count)</procedure> <procedure>(make-axis-right scale #!key label tick-count)</procedure> Convenience wrappers around: <procedure>(make-axis scale position #!key label tick-count tick-length tick-width label-size label-offset line-color)</procedure> ; {{position}} : {{'bottom}}, {{'top}}, {{'left}}, or {{'right}} ; {{tick-count}} : target number of ticks (default 5) ; {{tick-length}} : length of tick marks in user units (default 5) ; {{tick-width}} : stroke width of ticks (default 1) ; {{label-size}} : font size for tick labels (default 10.0) ; {{label-offset}} : distance from axis line to label anchor in user units (default 15) ; {{line-color}} : color string (default {{"black"}}) <procedure>(axis-drawer axis-config)</procedure> Return a drawer for the axis. The drawer is in axis-local coordinates (the axis line lies at x=0 for vertical axes, y=0 for horizontal ones); the caller must apply {{with-translate}} to place it at the panel edge. === Legends <procedure>(make-legend-continuous scale #!key title position width height label-size)</procedure> <procedure>(make-legend-discrete scale #!key title position width height label-size)</procedure> <procedure>(legend-drawer legend-config)</procedure> == Data format All geometries expect data as a columnar alist, an association list mapping column names (symbols) to lists of equal length: <enscript highlight="scheme"> ;; Columnar alist (required by the library) '((time . (0 10 20 30 40 50)) (response . (0.89 1.29 2.35 1.68 2.58 2.08)) (condition . ("A" "A" "A" "B" "B" "B"))) </enscript> Use {{columns->rows}} / {{rows->columns}} from {{gg-data}} to convert between row-oriented and column-oriented representations. ---- == Examples === Minimal scatter plot <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((x . (1 2 3 4 5)) (y . (2.1 3.8 2.9 5.1 4.3)))) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6 #:color "steelblue") (scale-x-continuous #:name "X") (scale-y-continuous #:name "Y") (theme-minimal) (labs #:title "Simple Scatter"))) (ggsave p "scatter.png" #:width 600 #:height 400) </enscript> === Time series with confidence ribbon <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 40 50 60 70 80 90 100)) (value . (0.89 1.29 2.35 1.68 1.15 1.81 2.58 2.08 1.57 1.94 2.35)) (upper . (1.66 1.95 2.72 2.12 1.71 2.21 2.96 2.39 2.00 2.27 2.67)) (lower . (0.55 0.83 1.56 0.75 0.76 1.16 2.19 1.50 0.91 1.16 2.00)))) (define p (ggplot data (aes #:x 'time #:y 'value) ;; Shaded confidence band (layer-area #:mapping (aes #:ymin 'lower #:ymax 'upper) #:fill "steelblue" #:alpha 0.3) ;; Central line and points (layer-line #:width 2 #:color "black") (layer-point #:size 5 #:color "black") (scale-x-continuous #:name "Time (seconds)") (scale-y-continuous #:name "Response (mV)") (theme-minimal #:base-size 12) (labs #:title "Time Series with Confidence Band" #:subtitle "Example of layered composition"))) (ggsave p "timeseries.png" #:width 800 #:height 600) </enscript> === Multi-series line plot with manual colors <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 40 50 60 0 10 20 30 40 50 60)) (value . (1.2 2.3 1.8 2.5 2.1 1.9 2.4 0.8 1.5 1.2 1.8 1.6 1.4 1.7)) (condition . ("Control" "Control" "Control" "Control" "Control" "Control" "Control" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment" "Treatment")))) (define p (ggplot data (aes #:x 'time #:y 'value #:color 'condition) (layer-line #:width 2) (layer-point #:size 4) (scale-x-continuous #:name "Time (ms)") (scale-y-continuous #:name "Response") (scale-color-manual #:values '(("Control" . "blue") ("Treatment" . "red"))) (theme-classic #:base-size 11) (labs #:title "Treatment vs Control"))) (ggsave p "multiseries.png" #:width 800 #:height 600) </enscript> === Bar chart with categorical x axis <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((region . ("V1" "V2" "V4" "MT" "IT")) (firing-rate . (12.5 8.3 15.7 22.1 9.4)))) (define p (ggplot data (aes #:x 'region #:y 'firing-rate) (layer-bar #:fill "steelblue" #:width 0.7) (scale-x-discrete #:name "Brain Region") (scale-y-continuous #:name "Firing Rate (Hz)" #:limits '(0 25)) (theme-bw) (labs #:title "Firing Rates Across Brain Regions"))) (ggsave p "bars.png" #:width 700 #:height 500) </enscript> === Spike raster (neuroscience event plot) <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define spike-data '((trial . (0 1 2 3 4 5 6 7 8 9)) (spikes . ((12 25 38 55 67) (15 28 42 58 71) (10 23 40 52 65) (18 30 45 60 73) (13 27 41 56 68) (16 29 43 59 72) (11 24 39 54 66) (14 26 44 57 70) (17 31 46 61 74) (9 22 37 53 64))) (condition . ("Pre" "Pre" "Pre" "Pre" "Pre" "Post" "Post" "Post" "Post" "Post")))) (define p (ggplot spike-data (aes #:x 'spikes #:y 'trial #:color 'condition) (layer-eventplot #:line-length 0.7 #:width 4) ;; Stimulus onset marker (layer-vline #:xintercept 20 #:color "red" #:linetype 'dashed #:width 1.5) (scale-x-continuous #:name "Time (ms)" #:limits '(0 80)) (scale-y-continuous #:name "Trial #") (scale-color-manual #:values '(("Pre" . "black") ("Post" . "royalblue"))) (theme-classic #:base-size 11) (labs #:title "Spike Raster Plot" #:subtitle "Pre vs Post stimulus"))) (ggsave p "raster.png" #:width 800 #:height 600) </enscript> === Logarithmic axes <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((concentration . (0.1 1 10 100 1000)) (response . (2.1 8.5 42.3 201.7 987.2)))) (define p (ggplot data (aes #:x 'concentration #:y 'response) (layer-point #:size 6 #:color "coral") (layer-line #:width 2 #:color "coral") (scale-x-log #:name "Concentration (uM)" #:base 10) (scale-y-log #:name "Response (% baseline)" #:base 10) (theme-minimal #:base-size 12) (labs #:title "Dose-Response Curve" #:subtitle "Log-log axes"))) (ggsave p "logscale.png" #:width 700 #:height 600) </enscript> === Faceted plot (small multiples) <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define data '((time . (0 10 20 30 0 10 20 30 0 10 20 30)) (power . (8 12 15 11 5 9 14 10 12 18 22 17)) (band . ("Alpha" "Alpha" "Alpha" "Alpha" "Beta" "Beta" "Beta" "Beta" "Gamma" "Gamma" "Gamma" "Gamma")))) (define p (ggplot data (aes #:x 'time #:y 'power) (layer-line #:color "steelblue" #:width 2) (layer-point #:size 4 #:color "darkblue") (facet-wrap 'band #:ncol 3 #:scales "free_y") (scale-x-continuous #:name "Time (s)") (scale-y-continuous #:name "Power (dB)") (theme-bw #:base-size 10) (labs #:title "Power Across Frequency Bands"))) (ggsave p "faceted.png" #:width 1200 #:height 400) </enscript> === Multiple output formats <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6) (theme-minimal) (labs #:title "Multi-format"))) ;; PNG raster (ggsave p "out.png" #:width 600 #:height 400) ;; High-resolution PNG (larger pixel dimensions) (ggsave p "out-hires.png" #:width 2400 #:height 1600) ;; SVG vector (ggsave p "out.svg" #:width 600 #:height 400) ;; PostScript (ggsave p "out.ps" #:width 600 #:height 400) ;; PDF (A4 portrait, dimensions in points) (render-plot p (make-cairo-pdf-backend "out.pdf" 595 842)) </enscript> === Plot specification serialisation <enscript highlight="scheme"> (import gg-plot gg-backend-cairo) (define p (ggplot data (aes #:x 'x #:y 'y) (layer-point #:size 6) (scale-x-continuous #:name "X") (scale-y-continuous #:name "Y") (theme-classic) (labs #:title "Saved plot"))) ;; Serialise to an s-expression and write to disk (define spec (plot->sexp p)) (with-output-to-file "my-plot.scm" (lambda () (write spec) (newline))) ;; Later: load and re-render (define restored (sexp->plot (with-input-from-file "my-plot.scm" read))) (ggsave restored "restored.png" #:width 700 #:height 500) </enscript> === Programmatic plot generation <enscript highlight="scheme"> ;; Build a plot that layers one line per variable (define (multi-line-plot data vars) (apply ggplot data (aes #:x 'time) (append (map (lambda (var) (layer-line #:mapping (aes #:y var) #:width 2)) vars) (list (scale-x-continuous #:name "Time (s)") (scale-y-continuous #:name "Value") (theme-minimal) (labs #:title (format "Variables: ~a" vars)))))) </enscript> ---- == Architecture notes === Scale training Scales are mutable: {{scale-train!}} extends the domain and {{scale-map}} reflects the updated domain. The plot pipeline trains each scale by scanning all layers before any geometry is rendered, which allows automatic axis limits that span the full data range across layers. === Drawer composition model All rendering is expressed as composable ''drawer'' values ({{drawer?}}). The pipeline builds one large combined drawer per panel and then executes it in a single pass over the plotter. === Author [[https://github.com/iraikov|Ivan Raikov]] === Repository [[https://github.com/iraikov/chicken-ggplot|https://github.com/iraikov/chicken-ggplot]] === Version History ; 1.0 : Initial release === License LPGL-3 === References * Wilkinson, Leland. The grammar of graphics. Springer Science & Business Media, 2005. * The R ggplot2 package is described in the manuscript, "A layered grammar of graphics", by Hadley Wickham in the Journal of Computational and Graphical Statistics, 2010.
Description of your changes:
I would like to authenticate
Authentication
Username:
Password:
Spam control
What do you get when you subtract 1 from 2?