---
title: "Simplevis"
author: "David Hodge"
date: "`r Sys.Date()`"
output: 
  rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Simplevis}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  message = FALSE,
  warning = FALSE,
  fig.height = 3.5, 
  fig.width = 6
)
```

```{r}
library(dplyr)
library(simplevis)
library(palmerpenguins)
library(ggplot2)
library(patchwork)
set.seed(123456789)
```

### Purpose 

`simplevis` is a package of `ggplot2` and `leaflet` wrapper functions that aims to make visualisation easier with less brainpower required.

### Visualisation families

`simplevis` supports many visualisation family types.

```{r, echo=FALSE, fig.width=8, fig.height=3}
plot_data <- penguins %>%
  group_by(species, sex) %>%
  summarise(body_mass_g = mean(body_mass_g, na.rm = TRUE))

p1 <- gg_bar_col(
  plot_data,
  y_var = body_mass_g,
  x_var = species,
  col_var = sex,
  col_na_rm = TRUE,
  size_width = 0.6,
  y_labels = function(x)
    x / 1000,
  y_title = "Body mass kg",
  title = "gg_bar*()"
)

p2 <- gg_boxplot_col(
  penguins,
  x_var = species,
  y_var = body_mass_g,
  col_var = sex,
  col_na_rm = TRUE,
  size_point = 0.5,
  y_labels = function(x)
    x / 1000,
  y_title = "Body mass kg",
  title = "gg_boxplot*()"
)

p1 + p2
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
p3 <- gg_density_col(
  penguins,
  x_var = body_mass_g,
  col_var = species,
  col_na_rm = TRUE,
  y_labels = scales::label_number(accuracy = 0.0001),
  x_breaks_n = 2,
  x_labels = function(x)
    x / 1000,
  x_title = "Body mass kg",
  title = "gg_density*()"
)

p4 <- gg_histogram_col(
  penguins,
  x_var = body_mass_g,
  col_var = species,
  col_na_rm = TRUE,
  x_breaks_n = 3,
  x_labels = function(x)
    x / 1000,
  y_labels = scales::label_comma(accuracy = 1),
  x_title = "Body mass kg",
  title = "gg_histogram*()"
)

p3 + p4
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
p5 <- gg_hbar_col(
  plot_data,
  x_var = body_mass_g,
  y_var = species,
  col_var = sex,
  col_na_rm = TRUE,
  size_width = 0.6,
  x_breaks_n = 3,
  x_labels = function(x)
    x / 1000,
  x_title = "Body mass kg",
  title = "gg_hbar*()"
)

p6 <- gg_hboxplot_col(
  penguins,
  x_var = body_mass_g,
  y_var = species,
  col_var = sex,
  col_na_rm = TRUE,
  size_point = 0.5,
  x_breaks_n = 2,
  x_labels = function(x)
    x / 1000,
  x_title = "Body mass kg",
  title = "gg_hboxplot*()"
)

p5 + p6
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
plot_data <- penguins %>%
  group_by(sex, species) %>%
  summarise(
    middle = median(body_mass_g, na.rm = TRUE),
    lower = quantile(body_mass_g, probs = 0.25, na.rm = TRUE),
    upper = quantile(body_mass_g, probs = 0.75, na.rm = TRUE)
  )

p7 <- gg_hpointrange_col(
  plot_data,
  xmiddle_var = middle,
  xmin_var = lower,
  xmax_var = upper,
  y_var = species,
  col_var = sex,
  col_na_rm = TRUE,
  x_breaks_n = 3,
  x_labels = function(x)
    x / 1000,
  x_title = "Body mass kg",
  size_point = 1,
  y_dodge = 0.3,
  title = "gg_hpointrange*()"
)

p8 <- gg_hviolin_col(
  penguins,
  x_var = body_mass_g,
  y_var = species,
  col_var = sex,
  x_breaks_n = 2,
  x_labels = function(x)
    x / 1000,
  x_title = "Body mass kg",
  col_na_rm = TRUE, 
  title = "gg_hviolin*()"
)

p7 + p8
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
plot_data <- penguins %>%
  group_by(year, species) %>% 
  summarise(body_mass_g = mean(body_mass_g, na.rm = T))

p9 <- gg_line_col(
  plot_data,
  x_var = year,
  y_var = body_mass_g,
  col_var = species,
  x_labels = scales::label_number(accuracy = 1, big.mark = "")
)

p10 <- gg_point_col(
  penguins,
  x_var = bill_length_mm,
  y_var = body_mass_g,
  col_var = species,
  x_breaks_n = 3,
  x_labels = scales::label_comma(accuracy = 1),
  y_labels = function(x) x / 1000,
  y_title = "Body mass kg",
  size_point = 0.5,
  title = "gg_point*()"
)

p9 + p10
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
plot_data <- penguins %>%
  group_by(sex, species) %>%
  summarise(
    middle = median(body_mass_g, na.rm = TRUE),
    lower = quantile(body_mass_g, probs = 0.25, na.rm = TRUE),
    upper = quantile(body_mass_g, probs = 0.75, na.rm = TRUE)
  )

p11 <- gg_pointrange_col(
  plot_data,
  x_var = sex,
  ymiddle_var = middle,
  ymin_var = lower,
  ymax_var = upper,
  col_var = species,
  x_na_rm = TRUE,
  x_dodge = 0.3,
  size_point = 1,
  y_labels = function(x) x / 1000,
  y_title = "Body mass kg",
  title = "gg_pointrange*()"
)

p12 <- gg_smooth_col(
  penguins,
  x_var = bill_length_mm,
  y_var = body_mass_g,
  col_var = species,
  size_point = 0.5,
  x_breaks_n = 3,
  x_labels = scales::label_comma(accuracy = 1),
  y_labels = function(x) x / 1000,
  y_title = "Body mass kg",
  title = "gg_smooth*()"
) 

p11 + p12
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
plot_data <- penguins %>%
  group_by(species, sex) %>%
  summarise(body_mass_g = mean(body_mass_g, na.rm = TRUE))

p13 <- gg_tile_col(
  plot_data,
  x_var = sex,
  y_var = species,
  col_var = body_mass_g,
  x_na_rm = TRUE,
  col_labels = scales::label_comma(accuracy = 1),
  title = "gg_tile*()"
)

p14 <- gg_violin_col(
  penguins,
  x_var = species,
  y_var = body_mass_g,
  col_var = sex,
  col_na_rm = TRUE,
  title = "gg_violin*()", 
  y_labels = function(x) x / 1000,
  y_title = "Body mass kg",
)

p13 + p14
```

```{r, echo=FALSE, fig.width=8, fig.height=3}
p15 <- gg_sf_col(
  example_point,
  col_var = trend_category,
  borders = example_borders,
  size_point = 0.5,
  title = "gg_sf*()"
)

p16 <- gg_stars_col(
  example_stars,
  col_var = nitrate,
  col_na_rm = TRUE,
  borders = example_borders,
  col_labels = scales::label_comma(accuracy = 1),
  title = "gg_stars*()"
)

p15 + p16
```

### 4 functions per family: colouring, facetting, neither or both 

Each visualisation family _generally_ has four functions.

This is based on whether or not a visualisation is to be:

* _not_ coloured by a variable and _not_ facetted (`*()`) 
* coloured by a variable, but _not_ facetted (`*_col()`)  
* facetted, but _not_ coloured by a variable (`*_facet()`)
* coloured by a variable and facetted (`*_col_facet()`)

The premise is that these are the most common types of visualisation for each of the families.

All arguments for variables are required unqutoted and follow an `*_var` format (i.e. `x_var`, `y_var`, `col_var` and `facet_var`)

For example, code below shows these combinations with code and output for the `gg_point*()` family.

```{r, fig.width = 5}
gg_point(penguins, 
         x_var = bill_length_mm, 
         y_var = body_mass_g)
```

```{r}
gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = sex)
```

```{r}
gg_point_facet(penguins, 
               x_var = bill_length_mm, 
               y_var = body_mass_g, 
               facet_var = species)
```

```{r, fig.width = 7}
gg_point_col_facet(penguins, 
                   x_var = bill_length_mm, 
                   y_var = body_mass_g, 
                   col_var = sex, 
                   facet_var = species)
```

### Customising plots

simplevis plots are designed to work and look clean with the bare minimum of code.

However, there is plenty of flexibility to customise.

#### Colour

Change the colour palette by supplying a vector of hex code colours to the `pal` argument. 

```{r}
gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = species, 
             pal = c("#da3490", "#9089fa", "#47e26f"))
```

Numerous colour palettes are available from the `pals` package.

simplevis also supports easy colouring of numeric variables for `gg_point*()`, `gg_bar*()`, `gg_hbar*()`, `gg_sf*()` and `gg_stars*()` (and equivalent leaflet functions).

The col_method argument allows you to specify the method for colouring with a default of continuous.

```{r}
gg_point_col(penguins, 
         x_var = bill_length_mm, 
         y_var = body_mass_g, 
         col_var = flipper_length_mm, 
         col_method = "continuous",
         subtitle = "col_method = 'continuous'")
```

Other methods available are `bin` and `quantile`.

For `bin` and `quantile`, you can fine-tune using the `col_breaks_n` or `col_cuts` arguments.

```{r, echo=FALSE, fig.width=8, fig.height=3}
p1 <- gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = flipper_length_mm, 
             col_method = "bin",
             size_point = 0.5,
             x_breaks_n = 3,
             x_labels = scales::label_comma(accuracy = 1),
             subtitle = "col_method = 'bin'")

p2 <- gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = flipper_length_mm, 
             col_method = "quantile",
             size_point = 0.5,
             x_breaks_n = 3,
             x_labels = scales::label_comma(accuracy = 1),
             col_labels = scales::label_comma(accuracy = 1),
             subtitle = "col_method = 'quantile'")
p1 + p2
```

You can also adjust the opacity of objects in the visualisation through the `alpha_*()` arguments.

Refer to the [colour](https://statisticsnz.github.io/simplevis/articles/colour.html) article for further information.

#### Themes

You can adjust the theme of any `simplevis` plot by providing a `ggplot2` theme to the `theme` argument.

```{r}
gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = species, 
             title = "A nice title", 
             subtitle = "And a subtitle",
             theme = ggplot2::theme_grey())
```

You can also create your own quick themes with the `gg_theme()` function.

```{r}
custom_theme <- gg_theme(
  pal_body = "white",
  pal_title = "white",
  pal_subtitle = "white",
  pal_background = c("#232323", "black"),
  pal_gridlines = "black", 
  gridlines_h = TRUE,
  gridlines_v = TRUE)

gg_point_col(penguins,
             species,
             x_var = bill_length_mm,
             y_var = body_mass_g, 
             theme = custom_theme)
```

Refer to the [themes](https://statisticsnz.github.io/simplevis/articles/themes.html) article for further information.

#### Consistent prefixes

There are lots of arguments available to modify the defaults.

In general, arguments have consistent prefixes based on `x_*`, `y_*`, `col_*` or `facet_*`, and as such the autocomplete can help identify what you need.

Some examples of transformations available are:

* `*_na_rm` to quickly not include NA observations
* `*_labels` to adjust labels for any x, y, col or facet scale
* `*_zero` to start at zero for numeric x or y scales 
* `*_breaks_n` for the number of numeric bins of breaks for the x, y or col scale to aim for 
* `*_rev` to reverse the order of categorical x, y or col scales in bars 
* `*_expand` to add padding to an x or y scale.
* `*_balance` to balance a numeric scale, so that zero is in the centre 
* `col_legend_none` to turn the legend off.

```{r}
plot_data <- storms %>%
  group_by(year, status) %>%
  summarise(wind = mean(wind))

gg_line_col(plot_data, 
           x_var = year, 
           y_var = wind, 
           col_var = status,
           x_breaks_n = 10,
           x_labels = function(x) stringr::str_sub(x, 3, 4),
           y_labels = scales::label_dollar(accuracy = 1), 
           col_labels = c("H", "TD", "TS"),
           y_zero = TRUE, 
           y_breaks_n = 10,
           y_expand = ggplot2::expansion(add = c(0, 10)))
```

Refer to the [scales](https://statisticsnz.github.io/simplevis/articles/scales.html) article for further information.

The `size_` and `alpha_` prefixes are used to modify the size and opacity of various aspects of the visualisation.

#### Titles

Defaults titles are: 

 * no title, subtitle or caption 
 * x, y and colour titles are converted to sentence case using the `snakecase::to_sentence_case` function. 

You can customise titles with `title`, `subtitle`, `x_title`, `y_title` and `caption` arguments. 

```{r}
gg_point_col(penguins, 
             x_var = bill_length_mm, 
             y_var = body_mass_g, 
             col_var = species, 
             title = "Adult penguin mass by bill length and species",
             subtitle = "Palmer station, Antarctica",
             x_title = "Bill length (mm)", 
             y_title = "Body mass (g)",
             col_title = "Species")
```

You can also request no x_title using `x_title = ""` or likewise for `y_title` and `col_title`.

### Maps

`simplevis` provides `sf` and `stars`  maps.

`sf` maps are maps of point, line or polygon features.

`stars` maps are maps of arrays (i.e. grids).

`sf` functions work in the same way as the ggplot2 graph functions, but with the following  differences:

* Data must be an `sf` object 
* Data must be of `POINT`/`MULTIPOINT`, `LINESTRING`/`MULTILINESTRING`, or `POLYGON`/`MULTIPOLYGON` geometry type
* Data must have a coordinate reference system (CRS) defined
* No `x_var` and `y_var` variables are required
* Borders can added to maps by providing an `sf` object to the `borders` argument. 

`stars` functions work in the same way as the ggplot2 graph functions, but with the following  differences:

* Data must be a `stars` object 
* Data must have a coordinate reference system (CRS) defined
* No `x_var` and `y_var` variables are required
* Borders can added to maps by providing an `sf` object to the `borders` argument. 

The following example objects are provided withing the package for learning purposes: `example_point`, `example_polygon` and `example_stars`.

The borders argument allows for the user to provide an sf object as context to the map (e.g. a coastline or administrative boundaries). An sf object of the New Zealand coastline has been provided to illustrate how this works.

```{r}
gg_sf_col(example_point, 
          col_var = trend_category, 
          borders = example_borders)
```

```{r}
gg_stars_col(example_stars,
             col_var = nitrate,
             col_method = "quantile",
             col_cuts = c(0, 0.05, 0.25, 0.5, 0.75, 0.95, 1),
             col_na_rm = TRUE,
             borders = example_borders)
```

simplevis also provides `leaflet` wrapper functions for `sf` and `stars` objects. These functions work in a similar way to the `gg_sf*()` and `gg_stars*()` functions, but have a `leaf_` prefix.

Refer to the [leaflet](https://statisticsnz.github.io/simplevis/articles/leaflet.html) article for further information.

### Extending simplevis 

All `gg_*` and `leaf_*` wrapper functions produce ggplot or leaflet objects. This means layers can be added to the functions in the same way you would a ggplot2 or leaflet object. Note you need to add _all_ aesthetics to any additional `geom_*` layers.

The below example adds error bars, labels, and a new y scale. Note that 25 percentiles and 75 percentiles have been used to demonstrate the errorbars, rather than confidence intervals which would normally be used with error bars.

```{r, fig.width = 4}
plot_data <- penguins %>%
  filter(!is.na(body_mass_g)) %>% 
  group_by(species) %>%
  summarise_boxplot_stats(body_mass_g) 

gg_bar_col(plot_data,
           x_var = species,
           y_var = middle,
           col_var = species,
           col_legend_none = TRUE,
           col_na_rm = TRUE,
           y_title = "Body mass g") +
  ggplot2::geom_errorbar(ggplot2::aes(x = species, ymin = lower, ymax = upper),
                         width = 0.2) +
  ggplot2::geom_text(ggplot2::aes(x = species, y = lower - 500, label = middle),
                     col = "white") +
  ggplot2::scale_y_continuous(
    name = "Body mass g",
    breaks = function(x) pretty(x, 5),
    limits = function(x) c(min(pretty(x, 5)), max(pretty(x, 5))),
    expand = c(0, 0)
  )            
```

The `patchwork` package can be used to patch visualisations together.

```{r}
library(patchwork)

p1 <- gg_point(penguins, 
               x_var = species, 
               y_var = body_mass_g, 
               x_jitter = 0.2, 
               alpha_point = 0.5) 

p2 <- gg_boxplot(penguins, 
                 x_var = species, 
                 y_var = body_mass_g) 

p1 + p2
```

All ggplot objects can be converted into interactive html objects using `plotly::ggplotly`. 

```{r, eval = FALSE}
plot <- gg_point_col(penguins,
                     x_var = bill_length_mm,
                     y_var = body_mass_g,
                     col_var = species)

plotly::ggplotly(plot) %>%
  plotly_camera()
```

`simplevis` also offers more customisability for making tooltips(i.e. hover values) in ggplotly (i.e. hover values). 

Refer to the [ggplotly](https://statisticsnz.github.io/simplevis/articles/ggplotly.html) article for further information.

### Supported variable classes

Variable types supported by the different families of functions are outlined below.

```{r, echo = FALSE, message = FALSE, warning = FALSE, fig.width = 7}
tibble::tribble(
  ~family, ~data, ~x_var, ~y_var, ~col_var, ~facet_var, 
  "bar", "tibble or data.frame", "Any*", "Numeric", "Categorical or numeric", "Categorical",
  "boxplot", "tibble or data.frame", "Categorical", "Numeric", "Categorical", "Categorical",
  "density", "tibble or data.frame", "Numeric", NA, "Categorical",  "Categorical", 
  "histogram", "tibble or data.frame", "Numeric", NA, "Categorical",  "Categorical", 
  "line", "tibble or data.frame", "Any", "Numeric", "Categorical", "Categorical",
  "point", "tibble or data.frame", "Any", "Numeric", "Categorical or numeric", "Categorical",
  "pointrange", "tibble or data.frame", "Any", "Numeric", "Categorical or numeric", "Categorical",
  "sf", "sf", NA, NA, "Categorical or numeric", "Categorical",
  "smooth", "tibble or data.frame", "Numeric", "Numeric", "Categorical", "Categorical",
  "stars", "stars", NA, NA, "Categorical or numeric", NA,
  "tile",  "tibble or data.frame", "Categorical", "Categorical", "Categorical or numeric", "Categorical",
  "violin", "tibble or data.frame", "Categorical", "Numeric", "Categorical", "Categorical", 
  "hbar", "tibble or data.frame", "Numeric", "Any*", "Categorical or numeric", "Categorical",
  "hboxplot", "tibble or data.frame", "Numeric", "Categorical", "Categorical", "Categorical",
  "hviolin", "tibble or data.frame", "Numeric", "Categorical", "Categorical", "Categorical", 
  "hpointrange", "tibble or data.frame", "Numeric", "Any", "Categorical or numeric", "Categorical"
  ) %>%
  DT::datatable(options = list(pageLength = 20, lengthChange = FALSE))
    
```

Where:

* Categorical refers to character, factor, or logical classes.
* Numeric refers to double or integer classes.
* Any* refers that if a numeric, date or datetime variable, values must be bins that are mutually exclusive and equidistant. 

### Further information

For further information, see the articles on the [simplevis](https://statisticsnz.github.io/simplevis/) website.