# Raincloud vignette

    library(ggrain)
    #> Loading required package: ggplot2
    #> Registered S3 methods overwritten by 'ggpp':
    #>   method                  from
    #>   heightDetails.titleGrob ggplot2
    #>   widthDetails.titleGrob  ggplot2

## The `geom_rain()` function

- handles as many rainclouds as you wish and can overlap them by a group
- connects within-subject observations longitudinally with lines using `id.long.var` argument
- colors dots by a covariate using the `cov` argument
- handles likert data by adding y-jittering with `likert = TRUE`
- changes orientation with `+ coord_flip()`

All individual elements of the plots can be edited, these are split into aesthetic and positioning arguments that are supplied by lists. For example the boxplots can be edited with `boxplot.args` and `boxplot.args.pos`, yet the others can also be edited by substituting for their name, i.e. `point/violin/line`. When you supply a list the defaults are overwritten so you may need to re-add them. To see the defaults run `?geom_rain`.

## Introduction

Here is our first plot which is just simply all the values of Sepal.Width in the iris dataset. For the function to work the value you want to plot must be given to the y argument in ggplot. You can then flip the plot with `+ coord_flip()` as we demonstrate below.

    ggplot(iris, aes(1, Sepal.Width)) +
      geom_rain() +
      theme_classic() +
      theme(axis.title.x = element_blank(),
            axis.text.x = element_blank(), axis.ticks.x = element_blank())

Let’s see what is happening over the 3 Species of flowers. The fill must be a factor or a character vector!

    ggplot(iris, aes(1, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2')

Let’s color the dots by Species, we do this by adding `color = Species` to ggplot. The default behavior of `geom_boxplot` is to color the lines in the boxplot showing the median and IQR. Therefore, we need to add a `boxplot.args` list to re-color the boxplot to black. When we do this all defaults are lost therefore we must add the options to not show outliers.

    ggplot(iris, aes(1, Sepal.Width, fill = Species, color = Species)) +
      geom_rain(alpha = .6,
                boxplot.args = list(color = "black", outlier.shape = NA)) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      scale_color_brewer(palette = 'Dark2')

It is also possible to nudge the box plots so they are not overlapping with `boxplot.args.pos`. We will also flip them by setting the rain.side argument to left (i.e., `'l'`).

    ggplot(iris, aes(1, Sepal.Width, fill = Species, color = Species)) +
      geom_rain(alpha = .5, rain.side = 'l',
                boxplot.args = list(color = "black", outlier.shape = NA),
                boxplot.args.pos = list(
                  position = ggpp::position_dodgenudge(x = .1, width = 0.1), width = 0.1
                )) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      scale_color_brewer(palette = 'Dark2') +
      guides(fill = 'none', color = 'none')

It could be even more useful to see the different species of flowers side by side rather than overlapping. The y value must be a factor or a character vector!

    ggplot(iris, aes(Species, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      guides(fill = 'none', color = 'none')

We can flip the plots by adding `coord_flip()`.

    ggplot(iris, aes(Species, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      guides(fill = 'none', color = 'none') +
      coord_flip()

This plot is a bit crammed, lets spread stuff out using the `boxplot.args.pos` & `violin.args.pos` arguments.

    ggplot(iris, aes(Species, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5,
                boxplot.args.pos = list(
                  width = 0.05, position = position_nudge(x = 0.13)),
                violin.args.pos = list(
                  side = "r",
                  width = 0.7, position = position_nudge(x = 0.2))) +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      guides(fill = 'none', color = 'none') +
      coord_flip()

Instead of coloring the dots by Species, the package offers the ability to color to another variable such as `Sepal.Length`. This will allow us to visualize how `Sepal.Width` and `Sepal.Length` relate to each other in each `Species` of flower. We can do this by adding them as a covariate with the `cov` argument. At the current time the argument must be given as a string.

    ggplot(iris, aes(Species, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .6,
                cov = "Sepal.Length") +
      theme_classic() +
      scale_fill_brewer(palette = 'Dark2') +
      guides(fill = 'none', color = 'none') +
      scale_color_viridis_c(option =  "A", direction = -1)

We will now take the species versicolor and virginica and make longitudinal data. We are going to see what fertilizer does to the Sepal.Width of both species!

    set.seed(42) # the magic number

    iris_subset <- iris[iris$Species %in% c('versicolor', 'virginica'),]

    iris.long <- cbind(rbind(iris_subset, iris_subset, iris_subset),
                       data.frame(time = c(rep("t1", dim(iris_subset)[1]), rep("t2", dim(iris_subset)[1]), rep("t3", dim(iris_subset)[1])),
                                  id = c(rep(1:dim(iris_subset)[1]), rep(1:dim(iris_subset)[1]), rep(1:dim(iris_subset)[1]))))

    # adding .5 and some noise to the versicolor species in t2
    iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t2"] <- iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t2"] + .5 + rnorm(length(iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t2"]), sd = .2)
    # adding .8 and some noise to the versicolor species in t3
    iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t3"] <- iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t3"] + .8 + rnorm(length(iris.long$Sepal.Width[iris.long$Species == 'versicolor' & iris.long$time == "t3"]), sd = .2)

    # now we subtract -.2 and some noise to the virginica species
    iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t2"] <- iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t2"] - .2 + rnorm(length(iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t2"]), sd = .2)

    # now we subtract -.4 and some noise to the virginica species
    iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t3"] <- iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t3"] - .4 + rnorm(length(iris.long$Sepal.Width[iris.long$Species == 'virginica' & iris.long$time == "t3"]), sd = .2)

    iris.long$Sepal.Width <- round(iris.long$Sepal.Width, 1) # rounding Sepal.Width so t2 data is on the same resolution
    iris.long$time <- factor(iris.long$time, levels = c('t1', 't2', 't3'))

Here we plot the species overlapping at each time point. We can see fertilizer caused the Sepal Width of the versicolor species to increase while the virginica species decreased slightly!

    ggplot(iris.long[iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5) +
      theme_classic() +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      guides(fill = 'none', color = 'none')

We can easily flank them using the `rain.side` argument for 2-by-2 flanking (i.e., `'f2x2'`). This also automatically uses `ggpp::position_dodgenudge` to dodge the boxplots. Yet, for descriptive purposes with will use the flanking argument `rain.side = 'f'` with the defaults from `'f2x2'`. The `rain.side = 'f'` argument defaults to a 2-by-2 yet throw a warning if you don’t remap the `violin.args.pos`. When using flanking with more groups or more time points you must give specific `boxplot.args.pos` and `violin.args.pos` for each element. The left elements must have negative x-axis nudging values with the right ones have positive x-axis nudging values.

For manual nudging of violins with quantiles please see the instructions on Github Issue 16.

    ggplot(iris.long[iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5, rain.side = 'f',
                 boxplot.args.pos = list(width = .1,
                    position = ggpp::position_dodgenudge(width = .1, #width needed now in ggpp version 0.5.g
                      x = c(-.13, -.13, # pre versicolor, pre virginica
                            .13, .13))), # post; post
                violin.args.pos = list(width = .7, quantiles = NULL,
                 position = position_nudge(x = c(rep(-.2, 512), rep(-.2, 512),# pre; pre
                                                 rep(.2, 512), rep(.2, 512))))) + #post; post
      theme_classic() +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      guides(fill = 'none', color = 'none')
    #> Warning: Using the `size` aesthetic with geom_polygon was deprecated in ggplot2 3.4.0.
    #> ℹ Please use the `linewidth` aesthetic instead.
    #> This warning is displayed once every 8 hours.
    #> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
    #> generated.

We can connect each plant with lines using the `id.long.var` argument, we will also use the convient `rain.side = 'f2x2'`. As with the `cov` argument, it must be a string linking the ids of each observation across time.

    ggplot(iris.long[iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5, rain.side = 'f2x2', id.long.var = "id") +
      theme_classic() +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      guides(fill = 'none', color = 'none')
    #> Warning: Duplicated aesthetics after name standardisation: alpha

We can color the dots and the connecting lines by Species! We will also remove the lines around the violins by specifying their `color = NA`, yet we now must re-add the alpha argument.

    ggplot(iris.long[iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species, color = Species)) +
      geom_rain(alpha = .5, rain.side = 'f2x2', id.long.var = "id",
                violin.args = list(color = NA, alpha = .7)) +
      theme_classic() +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      scale_color_manual(values=c("dodgerblue", "darkorange")) +
      guides(fill = 'none', color = 'none')
    #> Warning: Duplicated aesthetics after name standardisation: alpha

We can start to combine aspects, for example here is three timepoints with subjects connected, special flanking and a covariate mapped!

    ggplot(iris.long, aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5, rain.side = 'f', id.long.var = "id", cov = "Sepal.Length",
                boxplot.args = list(outlier.shape = NA, alpha = .8),
                violin.args = list(alpha = .8, color = NA),
                boxplot.args.pos = list(width = .1,
                 position = ggpp::position_dodgenudge(width = .1,
                                                      x = c(-.13, -.13, # t1 old, t1 young
                                                            -.13, .13,
                                                             .13, .13))),
                violin.args.pos = list(width = .7,
                 position = position_nudge(x = c(rep(-.2, 512), rep(-.2, 512),# t1
                                                 rep(-.2, 512), rep(.2, 512), # t2
                                                 rep(.2, 512), rep(.2, 512))))) +
      theme_classic() +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      scale_color_viridis_c(option =  "A", direction = -1) +
      guides(fill = 'none', color = 'none')
    #> Warning: Duplicated aesthetics after name standardisation: alpha
    #> Warning in x + params$x: longer object length is not a multiple of shorter
    #> object length
    #> Warning in x + params$x: longer object length is not a multiple of shorter
    #> object length
    #> Warning in x + params$x: longer object length is not a multiple of shorter
    #> object length

Lastly, we can add a mean trend line using `stat_summary`. Accentuating the opposite effects fertilizers had on the two species of flowers!

    ggplot(iris.long[iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5, rain.side = 'f2x2') +
      theme_classic() +
      stat_summary(fun = mean, geom = "line", aes(group = Species, color = Species)) +
      stat_summary(fun = mean, geom = "point",
                   aes(group = Species, color = Species)) +
      scale_fill_manual(values=c("dodgerblue", "darkorange")) +
      scale_color_manual(values=c("dodgerblue", "darkorange")) +
      guides(fill = 'none', color = 'none')

Here is some sample code on how to do a significance test on a 1-by-1 flanking raincloud with the package `ggsignif`. We will not run it as we don’t want to add `ggsignif` as a package dependency.

    ggplot(iris.long[iris.long$Species == 'versicolor' & iris.long$time %in% c('t1', 't2'),], aes(time, Sepal.Width, fill = Species)) +
      geom_rain(alpha = .5, rain.side = 'f1x1') +
     ggsignif::geom_signif(
      comparisons = list(c("t1", "t2")),
      map_signif_level = TRUE) +
    scale_fill_manual(values=c("darkorange", "darkorange")) +
    theme_classic()