17  Customization

How to customize plots: dimensions, labels, scales, mark styling, annotations, palettes, themes, legend placement, and interactivity.

(ns napkinsketch-book.customization
  (:require
   ;; Shared datasets for these docs
   [napkinsketch-book.datasets :as data]
   ;; Kindly β€” notebook rendering protocol
   [scicloj.kindly.v4.kind :as kind]
   ;; Napkinsketch β€” composable plotting
   [scicloj.napkinsketch.api :as sk]
   ;; Clojure2d β€” palette and gradient discovery
   [clojure2d.color :as c2d]))

Dimensions

A wide, short plot.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:width 800 :height 250}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

A tall, narrow plot.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:width 300 :height 500}))
sepal widthsepal lengthspeciessetosaversicolorvirginica56782.02.22.42.62.83.03.23.43.63.84.04.24.4

Titles and Labels

Override axis labels and add a title.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:title "Iris Sepal Measurements"
                 :x-label "Length (cm)"
                 :y-label "Width (cm)"}))
Iris Sepal MeasurementsWidth (cm)Length (cm)speciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Add a subtitle and caption for context.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:title "Iris Measurements"
                 :subtitle "Sepal dimensions across three species"
                 :caption "Source: Fisher's Iris dataset (1936)"}))
Iris MeasurementsSepal dimensions across three speciessepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5Source: Fisher's Iris dataset (1936)

Scales

Use a log scale for data spanning orders of magnitude.

(def exponential-data
  {:x (range 1 50)
   :y (map #(* 2 (Math/pow 1.1 %)) (range 1 50))})

Linear scale β€” hard to see the structure.

(-> exponential-data
    (sk/lay-point :x :y)
    (sk/options {:title "Linear Scale"}))
Linear Scaleyx05101520253035404550020406080100120140160180200220

Log y-scale β€” reveals the exponential trend.

(-> exponential-data
    (sk/lay-point :x :y)
    (sk/scale :y :log)
    (sk/options {:title "Log Y Scale"}))
Log Y Scaleyx05101520253035404550110100

Lock the y-axis to a specific range.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/scale :y {:type :linear :domain [0 6]})
    (sk/options {:title "Fixed Y Domain [0, 6]"}))
Fixed Y Domain [0, 6]sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.00123456

Mark Styling

Pass :alpha and :size directly to methods.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species :alpha 0.5 :size 5}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

:size controls line thickness on line-based marks:

(-> {:x [1 2 3 4 5] :y [2 4 3 5 4]}
    (sk/lay-line :x :y {:size 3}))
yx1.01.52.02.53.03.54.04.55.02.02.53.03.54.04.55.0

Alpha works on bars and polygons too.

(-> data/iris
    (sk/lay-bar :species {:alpha 0.4}))
speciessetosaversicolorvirginica05101520253035404550

Annotations

Add reference lines and shaded bands to highlight regions of interest.

Horizontal and vertical reference lines.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/lay (sk/rule-h 3.0) (sk/rule-v 6.0)))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Shaded bands use a default opacity of 0.15. Pass {:alpha …} to override.

(:band-opacity (sk/config))
0.15
(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/lay (sk/band-v 5.5 6.5) (sk/band-h 3.0 3.5 {:alpha 0.3})))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Custom Palette

Pass :palette to override the default color cycle.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:palette ["#E74C3C" "#3498DB" "#2ECC71"]}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

The palette applies to all color-mapped marks.

(-> data/penguins
    (sk/lay-stacked-bar :island {:color :species})
    (sk/options {:palette ["#8B5CF6" "#F59E0B" "#10B981"]}))
islandspeciesAdelieChinstrapGentooTorgersenBiscoeDream020406080100120140160

Pass a map to assign specific colors to specific categories.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:palette {:setosa "#E74C3C"
                           :versicolor "#3498DB"
                           :virginica "#2ECC71"}}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Named Palette Presets

Use a keyword to select a predefined palette. Napkinsketch accepts any palette name from the clojure2d color library, which includes hundreds of palettes from ColorBrewer, Wes Anderson, thi.ng, paletteer (R packages), and more.

Common examples:

  • :set1, :set2, :set3 β€” ColorBrewer qualitative
  • :pastel1, :pastel2 β€” ColorBrewer pastel
  • :dark2, :paired, :accent β€” ColorBrewer
  • :tableau10 β€” Tableau default
  • :category10 β€” D3 default

This is a small sample β€” thousands more are available. See the Discovering Palettes and Gradients section below.

See the Discovering Palettes and Gradients section below for how to search all available names.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:palette :set2}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Dark, high-contrast palette.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:palette :dark2}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Discovering Palettes and Gradients

Napkinsketch delegates color to the clojure2d library, which bundles thousands of named palettes and gradients. Use clojure2d.color/find-palette and clojure2d.color/find-gradient to search by regex pattern.

Find palettes whose name contains β€œbudapest”.

(c2d/find-palette #"budapest")
(:grand-budapest-1 :grand-budapest-2)

Find palettes whose name contains β€œset”.

(c2d/find-palette #"^:set")
(:set1 :set2 :set3)

Find gradients related to β€œviridis”.

(c2d/find-gradient #"viridis")
(:mpl/viridis
 :viridis/cividis
 :viridis/inferno
 :viridis/magma
 :viridis/mako
 :viridis/plasma
 :viridis/rocket
 :viridis/turbo
 :viridis/viridis)

c2d/palette returns the colors for a given name. Each color is a clojure2d Vec4 (RGBA, 0–255 range).

(c2d/palette :grand-budapest-1)
[[241.0 187.0 123.0 255.0]
 [253.0 100.0 103.0 255.0]
 [91.0 26.0 24.0 255.0]
 [214.0 114.0 54.0 255.0]]

Colorblind-friendly palettes

For presentations and publications, consider palettes designed for colorblind readers. Several good options are built in:

  • :set2 β€” muted qualitative, 8 colors
  • :dark2 β€” dark qualitative, 8 colors
  • :khroma/okabeito β€” designed specifically for color vision deficiency
  • :tableau-10 β€” Tableau default, high contrast
(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:palette :khroma/okabeito}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Theme

Customize background color, grid color, and font size.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:title "White Theme"
                 :theme {:bg "#FFFFFF" :grid "#EEEEEE" :font-size 10}}))
White Themesepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Legend Position

Control where the legend appears: :right (default), :bottom, :top, or :none.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:legend-position :bottom}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Tooltip

Enable mouseover data values with {:tooltip true}.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:tooltip true}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Brush Selection

Enable drag-to-select with {:brush true}. Click to reset.

(-> data/iris
    (sk/lay-point :sepal_length :sepal_width {:color :species})
    (sk/options {:brush true}))
sepal widthsepal lengthspeciessetosaversicolorvirginica4.55.05.56.06.57.07.58.02.02.53.03.54.04.5

Brushing becomes especially useful in a scatter plot matrix (SPLOM β€” scatter plot matrix). Drag to select points in any panel β€” the selection highlights across all panels, revealing multivariate structure.

(def splom-cols [:sepal_length :sepal_width :petal_length :petal_width])
(-> data/iris
    (sk/view (sk/cross splom-cols splom-cols) {:color :species})
    sk/lay-point
    (sk/options {:brush true}))
speciessetosaversicolorvirginica5678234246680122345012sepal lengthsepal widthpetal lengthpetal widthsepal lengthsepal widthpetal lengthpetal width

What’s Next

  • Faceting β€” split any chart into panels by one or two variables
  • API Reference β€” complete function listing with docstrings
source: notebooks/napkinsketch_book/customization.clj