---
title: "Using ggerror"
output:
  rmarkdown::html_vignette:
    css: vignette.css
vignette: >
  %\VignetteIndexEntry{Using ggerror}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}

---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  fig.width = 6,
  fig.height = 4,
  dpi = 96,
  warning = FALSE,
  message = FALSE
)
```

```{r imports}
library(ggplot2)
library(ggerror)
```

## Why `ggerror`?

Base `ggplot2` gives you several different error geoms, but using them means
deciding on orientation, which axis the error should follow, and how to
wire the lower and upper bounds correctly.
It creates a overhead and a cluncky DX.
`ggerror` collapses that into one layer and one error-focused API.

Everything in this vignette uses `mtcars`, so you can copy the examples
directly.

## Symmetric errors

```{r demo-data}
set.seed(1)
mt <- mtcars[sample(nrow(mtcars), 5), ]
mt$rn <- rownames(mt)

base_theme <- theme_minimal() + theme(
  plot.title = element_text(hjust = 0, family = "consolas", size = 12),
  axis.title = element_blank()
)

```

```{r base-plot}
p <- ggplot(mt, aes(mpg, rn)) +
  geom_point() + base_theme

p + geom_error(aes(error = drat))
```

`geom_error()` infers orientation from the data.
When one axis is discrete and the other is numeric, the error expands along the
numeric axis.
The default geom is `errorbbar`, which triggers under the hood `geom_errorbar()`.

## Choosing the error geom

You can pick the base range geom either through `error_geom` or via one of the
pinned wrapper functions.

```{r argument_or_pinned}
p + geom_error(aes(error = drat), error_geom = "crossbar")
p + geom_error_crossbar(aes(error = drat))
```

Supported values for `error_geom` are `"errorbar"`, `"linerange"`, `"crossbar"`, and
`"pointrange"`.

<div class="tip">
💡 **Tip:** Make use of `geom_error()` for a functional programming approach by using the `error_geom` argument with `purrr::map()`.
</div>

```{r functional-example, eval = requireNamespace("purrr", quietly = TRUE)}
supported_geoms <- c('errorbar', 'crossbar', 'linerange', 'pointrange')
purrr::map(supported_geoms, \(err) p + geom_error(aes(error = drat), error_geom = err))
```


## Asymmetric errors

Use `error_neg` and `error_pos` when the negative and positive extents differ.

```{r asymmetric-basic}
  p + geom_error(aes(
    error_neg = drat / 2,
    error_pos = drat)
    )
```

`error_neg` extends in the negative direction and `error_pos` extends in the
positive direction, regardless of whether the error is horizontal or vertical.
Both must be supplied together.
Not having to deal with orientation and `min`/`max` reduces overhead and ensures you stay focused on displaying the data, rather than the mechanics of the plot.

## One-sided bars

Setting one side to `0` gives you a one-sided error bar.

```{r one-sided}
p +
  geom_error(aes(
    error_neg = 0,
    error_pos = drat),
    width_neg = 0
  )
```

On its own, `aes(error_neg = 0, error_pos = drat)` still draws a cap at the
observation value at the default width, because the negative side has zero
length but inherits the shared cap width.
Setting `width_neg = 0` removes that cap and gives you a genuine one-sided
bar.

## More customization: per-side styling

For finer control, the negative and positive sides can be styled separately
with fixed `_neg` and `_pos` parameters for `colour`, `fill`, `linewidth`,
`linetype`, `alpha`, and `width`.

```{r asymmetric-styled}
p +
  geom_error(aes(
    error_neg = drat / 2,
    error_pos = drat),

    colour_neg = "steelblue",
    colour_pos = "firebrick",
    linewidth = 2 # you can still control both sides of the error bar
  )
```

```{r asymmetric-styled2}
p +
  geom_error(aes(
    error_neg = drat / 2,
    error_pos = drat),
    
    error_geom = "crossbar",
    fill_neg = "grey90",
    fill_pos = "grey30",
    width_neg = 0.2,
    width_pos = 0.6
  )
```

## Extending ggerror

If you know of, or need, a new error geom, please open an issue on the [GitHub repository](https://github.com/iamyannc/ggerror/issues).
My first motiviation was to simplify the heck out of the error geoms, reducing the aesthetics to a single `error` aesthetic. The rest (asymmetric, one-sided, etc) are just niceties that I added along the way.


