20  Faceting

Faceting splits data into subsets and draws each in its own panel, making it easy to compare patterns across groups.

(ns plotje-book.faceting
  (:require
   ;; Rdatasets -- standard datasets
   [scicloj.metamorph.ml.rdatasets :as rdatasets]
   ;; Kindly -- notebook rendering protocol
   [scicloj.kindly.v4.kind :as kind]
   ;; Plotje -- composable plotting
   [scicloj.plotje.api :as pj]))

Facet Wrap

pj/facet splits a pose into panels by one categorical column. The default direction is :col – a horizontal row of panels:

(-> (rdatasets/datasets-iris)
    (pj/lay-point :sepal-length :sepal-width {:color :species})
    (pj/facet :species))
sepal widthsepal lengthspeciessetosaversicolorvirginica682.02.53.03.54.04.56868setosaversicolorvirginica

Each species gets its own panel with a strip label on top. Scales are shared by default – all panels use the same x and y range, making direct comparison easy.

Vertical Facet

Pass :row as the direction for a vertical column of panels:

(-> (rdatasets/datasets-iris)
    (pj/lay-point :sepal-length :sepal-width {:color :species})
    (pj/facet :species :row))
sepal widthsepal lengthspeciessetosaversicolorvirginica2342344.55.05.56.06.57.07.58.0234setosaversicolorvirginica

Facet Grid

pj/facet-grid splits by two columns – one for rows, one for columns:

(-> (rdatasets/reshape2-tips)
    (pj/lay-point :total-bill :tip {:color :sex})
    (pj/facet-grid :smoker :sex))
tiptotal billsexFemaleMale51020405102040NoYesFemaleMale

Row labels appear on the right, column labels on top.

Faceted Histogram

(-> (rdatasets/datasets-iris)
    (pj/lay-histogram :sepal-length {:color :species})
    (pj/facet :species))
sepal lengthspeciessetosaversicolorvirginica6802468101214166868setosaversicolorvirginica

Faceted Regression

Layers compose with faceting – scatter plus regression per panel:

(-> (rdatasets/reshape2-tips)
    (pj/pose :total-bill :tip {:color :sex})
    pj/lay-point
    (pj/lay-smooth {:stat :linear-model})
    (pj/facet-grid :smoker :sex))
tiptotal billsexFemaleMale51020405102040NoYesFemaleMale

Free Scales (Independent Axis Ranges)

By default all panels share the same axis ranges. Use the :scales option to let axes vary per panel.

Shared (default) – all panels carry the same x and y ranges:

(-> (rdatasets/datasets-iris)
    (pj/lay-point :sepal-length :sepal-width {:color :species})
    (pj/facet :species)
    (pj/options {:scales :shared}))
sepal widthsepal lengthspeciessetosaversicolorvirginica682.02.53.03.54.04.56868setosaversicolorvirginica

Free y – each panel has its own y-range:

(-> (rdatasets/datasets-iris)
    (pj/lay-point :sepal-length :sepal-width {:color :species})
    (pj/facet :species)
    (pj/options {:scales :free-y}))
sepal widthsepal lengthspeciessetosaversicolorvirginica682.22.42.62.83.03.23.43.63.84.04.24.46868setosaversicolorvirginica

Other values: :free-x (x per-panel, y shared), :free (both axes per-panel).

A related multi-panel layout, the scatter plot matrix (SPLOM), uses pj/cross rather than pj/facet – the panels show all pairs of variables instead of one variable split across panels. See the Relationships chapter for the canonical SPLOM example.

Comparing Multiple Columns

Pass a vector of column names to create one panel per column:

(pj/lay-histogram (rdatasets/datasets-iris) [:sepal-length :sepal-width :petal-length] {:color :species})
68024681012141623402468101214161850510152025sepal lengthsepal widthpetal lengthspeciessetosaversicolorvirginica

Faceted Bar Chart

Five bars total across the three island panels: Adelie appears on every island, while Gentoo lives only on Biscoe and Chinstrap only on Dream. Empty species-island combinations produce no bar.

(-> (rdatasets/palmerpenguins-penguins)
    (pj/lay-bar :species {:color :species})
    (pj/facet :island))
speciesspeciesAdelieGentooChinstrapAdelieGentooChinstrap020406080100120AdelieGentooChinstrapAdelieGentooChinstrapTorgersenBiscoeDream

Labels and Faceting

pj/options works with faceted plots:

(-> (rdatasets/datasets-iris)
    (pj/lay-point :sepal-length :sepal-width {:color :species})
    (pj/facet :species)
    (pj/options {:title "Iris by Species"
                 :x-label "Sepal Length (cm)" :y-label "Sepal Width (cm)"}))
Iris by SpeciesSepal Width (cm)Sepal Length (cm)speciessetosaversicolorvirginica682.02.53.03.54.04.56868setosaversicolorvirginica

See Also

  • Composition – composite poses, shared scales, and arbitrary layouts
  • Core Concepts – mapping scope as it flows through faceted panels

What’s Next

source: notebooks/plotje_book/faceting.clj