Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"

[compat]
AlgebraOfGraphics = "0.6, 0.7, 0.8"
AlgebraOfGraphics = "0.6, 0.7, 0.8, 0.9, 0.10"
Arrow = "2"
CSV = "0.10"
CairoMakie = "0.11, 0.12"
CairoMakie = "0.11 - 0.22"
CategoricalArrays = "0.10"
Chain = "0.5,0.6"
DataAPI = "1"
Expand Down
9 changes: 5 additions & 4 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ project:
- "/fonts/*"

book:
title: "Embrace Uncertainty"
title: "Embrace Uncertainty (Preview)"
subtitle: "Mixed-effects models with Julia"
author:
author:
- name: Phillip Alday
email: [email protected]
orcid: 0000-0002-9984-5745
Expand Down Expand Up @@ -45,6 +45,7 @@ book:
- datatables.qmd
- linalg.qmd
- aGHQ.qmd
- algebraofgraphics.qmd

execute-dir: project

Expand All @@ -62,15 +63,15 @@ format:
html:
# for more info, see
# https://quarto.org/docs/output-formats/html-themes.html
theme: [sandstone, theme.scss]
theme: [cosmo, theme.scss]
# sets the background of inline code and code output but not code blocks?
# also overrides code-bg in the SCSS file
# monobackgroundcolor: '#fafafa'

engine: julia

julia:
exeflags:
exeflags:
- --project
- -tauto

Expand Down
170 changes: 170 additions & 0 deletions algebraofgraphics.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
fig-width: 4
fig-height: 3
fig-dpi: 150
fig-format: png
engine: julia
execute:
cache: true
julia:
exeflags: ["--project"]
---

# Algebra of Graphics {#sec-aog}

In this appendix, we give a demonstration of and introduction to the [`AlgebraOfGraphics`](https://aog.makie.org/) package and plotting system.
The key concepts in `AlgebraOfGraphics` (or AoG for short) are layers, the `+` operator, and the `*` operator.
Each layer in an AoG plot consists of at least (1) a mapping from the data to the plot elements (such as the x-axis, y-axis, and color), and (2) a visual that defines the type of plot (for example, scatterplot or lines), which are combined using the `*` operator.
The mapping is analogous to the "aesthetic mapping" in the grammar-of-graphics based [`ggplot2`](https://ggplot2.tidyverse.org) package in `R` and the visual is the same as a "geom".
While the `+` operator allows us to stack layers together, the `*` operator allows us to both construct a layer and modify multiple layers at once.
Once we have constructed the layers of a plot, we can display or print the plot using the `draw` function.
Additionally, the draw function allows us to apply modifications that do not depend on the data to common elements in the plot.
While this may all sound very abstract we will see these concepts in action shortly.

## A plot with a single layer

To illustrate the principles briefly explained above, we plot the `elstongrizzle` dataset in multiple ways building up to the plots in @sec-longitudinal.
We start off we first plot the length of Ramus bone against time for all subjects.
To do so we first load all the relevant packages,

```{julia}
#| code-fold: true
#| output: false
#| label: app-aog-packages
using AlgebraOfGraphics
using CairoMakie
using DataFrames, DataFrameMacros
using GLM # for the lm needed to arrange the final plot
using EmbraceUncertainty: dataset
```
and the dataset:

```{julia}
#| code-fold: true
#| output: false
#| label: app-aog-data
elstongrizzle = DataFrame(dataset(:elstongrizzle))
```

The scatter-plot is defined by the mapping from the data to the $x$ and $y$ axis of the plots.

```{julia}
ramusscatter = data(elstongrizzle) * mapping(:time, :resp) * visual(Scatter)
```


```{julia}
draw(ramusscatter)
```

This plot is not very useful because the points for all the subjects are mixed in together.
To distinguish data for different subjects, let's color the data points by subject.
This means that we must map the subject ID (`Subj`) to the `color` attribute of the plot.

```{julia}
draw(ramusscatter*mapping(color = :Subj))
```

Although this worked, the more concise way to achieve the same thing is to define all the mappings at once as follows:
```{julia}
egscatter = data(elstongrizzle) *
mapping(:time, :resp, color = :Subj) *
visual(Scatter)
draw(egscatter)
```


## Adding another layer

To construct a layer for lines, we can use the `visual(Lines)`:
```{julia}
eglines = data(elstongrizzle) *
mapping(:time, :resp, color = :Subj) *
visual(Lines)

draw(eglines)
```

We can now combine the layers by simply using `+`!

```{julia}
draw(egscatter + eglines)
```

You may have noticed that the mapping from the data to the plot elements is the same for both layers is the same.
This is where the power of the algebra comes in.
We can define two layers with the same mapping using the following code:
```{julia}
egscatterlines = data(elstongrizzle) *
mapping(:time, :resp, color = :Subj) *
(visual(Scatter) + visual(Lines))
```
Let's unpack this.
We can define two partial layers with `visual(Scatter) + visual(Lines)` and both are defined with the common mapping, which we can achieve by modifying, i.e. using the `*` operator on the stack of two (partial) layers.
To confirm if this actually works, we can just invoke `draw`:
```{julia}
draw(egscatterlines)
```
and _voila_ we just created two layers at once!


## Modifying common elements with `draw`

One issue with the plot above is that the legend is far too big to fit vertically on the side.
So let's try putting at the bottom of the plot.
This is an action that is not related to any single layer, and can be modified using optional arguments to the draw method as follows:
```{julia}
draw(
egscatterlines;
legend = (; position = :bottom, titleposition = :left)
)
```

Note that we reused the object `egscatterlines` which is a stack of layers from before.
While this is better than before, the individual subject names are not really relevant to this plot, so let's remove the legend altogether.

:::{.callout-note}
**TODO:** How to explain why legend is disabled in the `scales`?
:::

```{julia}
draw(
egscatterlines,
scales(Color = (; legend = false))
)
```

The `scales` argument can also be used to modify other features of plot elements.
To demonstrate this, we change the color palette used for plotting to `darktest` color palette (See [`Makie.jl` documentation](https://docs.makie.org/stable/explanations/colors#misc)).

```{julia}
#| label: fig-scatterline-dartest
#| fig-cap: Scatter-plot with overlaid lines using the `darktest` colorscheme
draw(
egscatterlines,
scales(Color = (; legend = false, palette = :darktest))
)
```

## Faceting

@fig-scatterline-dartest is still crowded, and one way to fix this would be to plot each subject in a separate panel.
In `ggplot2` this is achieved by using `facet`.
Since we want to facet by `Subj`, we need to map a feature of the data (`Subj`) to an element of the plot.
Thus, we must define some sort of mapping to achieve this.
In this case, we want to use the equivalent of `ggplot2::facet_wrap`, which is the `layout` element of the feature. Similar to mapping the subject ID to color, we can map `Subj` to `layout` as follows:
```{julia}
draw(
egscatterlines * mapping(layout = :Subj),
scales(Color = (; legend = false, palette = :darktest));
figure = (; size = (800, 400))
)
```

It is also possible to facet by two features, one along the horizontal direction and one along the vertical direction using the `col` and `row` (this would be akin to `ggplot2::facet_grid`) keyword arguments in the mapping.

:::{.callout-note}

**TODO:** use the `layout` keyword mapping to create facets by subject instead of colors by subject

:::
15 changes: 5 additions & 10 deletions intro.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ fig-height: 3
fig-dpi: 150
fig-format: png
engine: julia
execute:
cache: true
julia:
exeflags: ["--project"]
---
Expand Down Expand Up @@ -239,7 +241,7 @@ For example, four of the five preparations from batch F produced lower yields th

This plot, and essentially all the other plots in this book, were created using the [Makie](https://makie.juliaplots.io) package [@DanischKrumbiegel2021].

In `yet-to-be-written-appendix` we review some of the principles of data graphics, such as reordering the levels of the factor by increasing mean response, that enhance the informativeness of the plot.
In @sec-aog we review some of the principles of data graphics, such as reordering the levels of the factor by increasing mean response, that enhance the informativeness of the plot.
For example, in this plot the levels of `batch` are sorted by increasing mean yield, to make visual comparisons between batches easier, and the vertical positions are *jittered* to avoid overplotting of points.
(Note that the two lowest yields of samples from batch `A` are identical.)

Expand Down Expand Up @@ -675,13 +677,6 @@ The apparent distribution of the estimates of $\sigma_1$ in @fig-dsm01_bs_sigma_
A [kernel density estimate](https://en.wikipedia.org/wiki/Kernel_density_estimation) approximates a probability density from a finite sample by blurring or smearing the positions of the sample values according to a *kernel* such as a narrow Gaussian distribution (see the linked article for details).
In this case the distribution of the estimates is a combination of a continuous distribution and a spike or point mass at zero as shown in a histogram, @fig-dsm01_bs_sigma_hist.

:::{.callout-note collapse="true"}

### Adjust the alpha in multiple histograms

Use a lower alpha in the colors for multiple histograms so the bars behind another color are more visible
:::

```{julia}
#| code-fold: true
#| fig-cap: Histogram of bootstrap variance-components as standard deviations from model dsm01
Expand All @@ -693,7 +688,7 @@ draw(
:value => "Bootstrap parameter estimates of σ";
color=(:group => "Group"),
) *
AlgebraOfGraphics.histogram(; bins=80);
AlgebraOfGraphics.histogram(; bins=80) * visual(alpha = 0.4);
figure=(; size=(600, 340)),
)
```
Expand Down Expand Up @@ -724,7 +719,7 @@ draw(
:value_abs2 => "Bootstrap sample of estimates of σ²",
color=:group,
) *
AlgebraOfGraphics.histogram(; bins=200);
AlgebraOfGraphics.histogram(; bins=200) * visual(alpha = 0.4);
figure=(; size=(600, 340)),
)
```
Expand Down
Loading