R/ggplot_themes.R

#' Personalised ggplot theme.
#'
#' Personal ggplot theme that relies on Ubuntu font.
#'
#' @param base_size Font size.
#' @param base_family Font family.
#' @param base_line_size Line thickness. Relative to font size by default.
#' @param base_rect_size Rectangle line thickness. Relative to font size by default.
#' @param legend Location of legend. Can be removed ("none"), "bottom", "top", "left", "right".
#' @param tick_margins Distance of tick values from the ticks. Larger value mean larger distance.
#'
#' @return A ggplot theme
#' @export
#' @import extrafont
#' @import ggplot2
#' @importFrom utils menu
#'
#' @examples
#' library(ggplot2)
#' library(extrafont)
#'
#' ggplot(iris)+
#' geom_point(aes(x = Petal.Length, y = Petal.Width))+
#' theme_ubuntu()

theme_ubuntu <- function(base_size = 12, base_family = "Ubuntu",
                         base_line_size = base_size / 20,
                         base_rect_size = base_size / 20,
                         tick_margins = 0.8, legend = "none") {

  if(!base_family %in% extrafont::fonts()){

    user_response <- menu(choices = c("Use default font", paste0("Load ", base_family)),
         title = paste0("The font family ", base_family, " does not exist. What would you like to do?"))

    if(user_response == 1){

      base_family <- "Arial"

    } else {

      extrafont::font_import(pattern = base_family)

    }

  }

  half_line <- base_size / 2

  theme(
    # Elements in this first block aren't used directly, but are inherited
    # by others. These set the defaults for line, rectangle and text elements.
    line = element_line(colour = "black", size = base_line_size,
                        linetype = 1, lineend = "round"),
    rect = element_rect(fill = "white", colour = "black",
                        size = base_rect_size, linetype = 1),
    text = element_text(family = base_family, face = "plain",
                        colour = "black", size = base_size,
                        lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
                        margin = margin(), debug = FALSE),

    #These just follow the default line characteristics
    axis.line   = NULL,
    axis.line.x = NULL,
    axis.line.y = NULL,

    #These affect the ticks and tick text in all circumstances (e.g. top and bottom axis)
    axis.text         = element_text(size = rel(0.8), face = "bold"),
    axis.text.x       = element_text(margin = margin(t = tick_margins * half_line / 2), vjust = 1),
    axis.text.x.top   = element_text(margin = margin(b = tick_margins * half_line / 2), vjust = 0),
    axis.text.y       = element_text(margin = margin(r = tick_margins * half_line / 2), hjust = 1),
    axis.text.y.right = element_text(margin = margin(l = tick_margins * half_line / 2), hjust = 0),
    axis.ticks        = element_line(colour = "black", lineend = "round", size = ),
    axis.ticks.length = unit(half_line / 2, "pt"),

    #These affect the axis labels
    axis.title.x       = element_text(margin = margin(t = half_line * 1.5),
                                      vjust = 1, face = "bold"),
    axis.title.x.top   = element_text(margin = margin(b = half_line),
                                      vjust = 0, face = "bold"),
    axis.title.y       = element_text(angle = 90, margin = margin(r = half_line * 1.5),
                                      vjust = 0, face = "bold"),
    axis.title.y.right = element_text(angle = -90, margin = margin(l = half_line),
                                      vjust = 0, face = "bold"),

    #These affect plot legends
    legend.background = element_rect(colour = NA),
    legend.spacing    = unit(2 * half_line, "pt"),
    legend.spacing.x  = NULL,
    legend.spacing.y  = NULL,
    legend.margin     = margin(half_line, half_line, half_line, half_line),
    legend.key        = element_rect(fill = NA, colour = "white"),
    legend.key.size   = unit(1.2, "lines"),
    legend.key.height = NULL,
    legend.key.width  = NULL,
    legend.position   = legend,
    legend.text       = element_text(family = base_family, size = rel(0.8)),

    #These affect the background of the whole panel (plotting area and outside plotting area)
    panel.background = element_rect(fill = "white", colour = NA),
    panel.border     = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.spacing    = unit(half_line, "pt"),
    panel.spacing.x  = NULL,
    panel.spacing.y  = NULL,
    panel.ontop      = FALSE,

    #These affect the plot headers if faceting
    strip.background      = element_rect(fill = NA, colour = "black"),
    strip.text            = element_text(size = rel(0.8),
                                         margin = margin(half_line, half_line,
                                                         half_line, half_line)),
    strip.text.x          = NULL,
    strip.text.y          = element_text(angle = -90),
    strip.placement       = "inside",
    strip.placement.x     =  NULL,
    strip.placement.y     =  NULL,
    strip.switch.pad.grid = unit(0.1, "cm"),
    strip.switch.pad.wrap = unit(0.1, "cm"),

    #These affect the plot area itself (not around the axes)
    plot.background = element_rect(colour = "white"),
    plot.title      = element_text(size = rel(1.2), hjust = 0.5, vjust = 1,
                                   margin = margin(b = half_line * 1.2)),
    plot.subtitle   = element_text(size = rel(0.9), hjust = 0.5, vjust = 1,
                                   margin = margin(b = half_line * 0.9)),
    plot.caption    = element_text(size = rel(0.9), hjust = 0.5, vjust = 1,
                                   margin = margin(t = half_line * 0.9)),
    plot.margin     = margin(half_line, half_line, half_line, half_line),

    complete = TRUE
  )
}

############################################

#' Extension of theme_ubuntu for maps
#'
#' Extension of the theme_ubuntu ggplot theme, but designed for maps.
#'
#' @param base_size Font size.
#' @param base_family Font family.
#' @param base_line_size Line thickness. Relative to font size by default.
#' @param base_rect_size Rectangle line thickness. Relative to font size by default.
#' @param legend Location of legend. Can be removed ("none"), "bottom", "top", "left", "right".
#'
#' @return A ggplot theme.
#' @export
#'
#' @examples
#' library(ggplot2)
#'
#' ggplot(iris)+
#' geom_point(aes(x = Petal.Length, y = Petal.Width))+
#' theme_umap()

theme_umap <- function(base_size = 12, base_family = "Ubuntu",
                       base_line_size = base_size / 20,
                       base_rect_size = base_size / 20,
                       legend = "none") {

  half_line <- base_size / 2

  if(legend == "left" | legend == "right"){

    dir   =   "vertical"
    stack =   "vertical"

  } else {

    dir   = "horizontal"
    stack = "vertical"

  }

  theme_ubuntu()+
    theme(

      #Remove all axes components
      axis.line  = element_blank(),
      axis.text  = element_blank(),
      axis.ticks = element_blank(),
      axis.title = element_blank(),

      #Affect legend
      legend.position = legend,
      legend.direction = dir,
      legend.box = stack,
      legend.spacing =     unit(0.4, "cm"),
      legend.margin =      margin(0.2, 0.2, 0.2, 0.2, "cm"),
      legend.key =         element_blank(),
      legend.key.size =    unit(1.2, "lines"),
      legend.text =        element_text(size = rel(1.3)),
      legend.title =       element_text(hjust = 0, face = "bold"),
      legend.title.align = 0.5,
      legend.justification = "center",
      legend.box.margin =  margin(0, 0, 0, 0, "cm"),
      legend.box.background = element_blank(),
      legend.box.spacing = unit(0.4, "cm"),

      #Affect facets
      strip.background =   element_rect(fill = "white", colour = "black"),
      strip.placement =    "outside",

      aspect.ratio = 1,

      complete = TRUE
  )
}

############################################

#' Light theme for creating plots
#'
#' @param base_size Font size.
#' @param base_family Font family.
#' @param base_line_size Line thickness. Relative to font size by default.
#' @param base_rect_size Rectangle line thickness. Relative to font size by default.
#' @param legend Location of legend. Can be removed ("none"), "bottom", "top", "left", "right".
#' @param tick_margins Distance between tick and text.
#'
#' @return ggplot theme
#' @export

theme_tidylight <- function(base_size = 12, base_family = "Arial Rounded MT Bold",
                        base_line_size = base_size / 20,
                        base_rect_size = base_size / 20,
                        tick_margins = 0.8, legend = "none") {

  if(!base_family %in% extrafont::fonts()){

    user_response <- menu(choices = c("Use default font", paste0("Load ", base_family)),
                          title = paste0("The font family ", base_family, " does not exist. What would you like to do?"))

    if(user_response == 1){

      base_family <- "Arial"

    } else {

      extrafont::font_import(pattern = base_family)

    }

  }

  half_line <- base_size / 2

  theme(
    # Elements in this first block aren't used directly, but are inherited
    # by others. These set the defaults for line, rectangle and text elements.
    line = element_line(colour = "black", size = base_line_size,
                        linetype = 1, lineend = "round"),
    rect = element_rect(fill = "white", colour = "black",
                        size = base_rect_size, linetype = 1),
    text = element_text(family = base_family, face = "plain",
                        colour = "black", size = base_size,
                        lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
                        margin = margin(), debug = FALSE),

    #These affect the ticks and tick text in all circumstances (e.g. top and bottom axis)
    axis.text         = element_text(size = rel(0.8), face = "bold"),
    axis.text.x       = element_text(margin = margin(t = tick_margins * half_line / 2), vjust = 1),
    axis.text.x.top   = element_text(margin = margin(b = tick_margins * half_line / 2), vjust = 0),
    axis.text.y       = element_text(margin = margin(r = tick_margins * half_line / 2), hjust = 1),
    axis.text.y.right = element_text(margin = margin(l = tick_margins * half_line / 2), hjust = 0),
    axis.ticks        = element_line(colour = "black", lineend = "round", size = ),
    axis.ticks.length = unit(half_line / 2, "pt"),

    #These affect the axis labels
    axis.title.x       = element_text(margin = margin(t = half_line * 1.5),
                                      vjust = 1, face = "bold"),
    axis.title.x.top   = element_text(margin = margin(b = half_line),
                                      vjust = 0, face = "bold"),
    axis.title.y       = element_text(angle = 90, margin = margin(r = half_line * 1.5),
                                      vjust = 0, face = "bold"),
    axis.title.y.right = element_text(angle = -90, margin = margin(l = half_line),
                                      vjust = 0, face = "bold"),

    #These affect plot legends
    legend.background = element_rect(colour = NA),
    legend.spacing    = unit(2 * half_line, "pt"),
    legend.spacing.x  = NULL,
    legend.spacing.y  = NULL,
    legend.margin     = margin(half_line, half_line, half_line, half_line),
    legend.key        = element_rect(fill = NA, colour = "white"),
    legend.key.size   = unit(1.2, "lines"),
    legend.key.height = NULL,
    legend.key.width  = NULL,
    legend.position   = legend,
    legend.text       = element_text(family = base_family, size = rel(0.8)),

    #These affect the background of the whole panel (plotting area and outside plotting area)
    panel.background = element_rect(fill = "white", colour = NA),
    panel.border     = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.spacing    = unit(half_line, "pt"),
    panel.spacing.x  = NULL,
    panel.spacing.y  = NULL,
    panel.ontop      = FALSE,

    #These affect the plot headers if faceting
    strip.background      = element_rect(fill = NA, colour = "black"),
    strip.text            = element_text(size = rel(0.8),
                                         margin = margin(half_line, half_line,
                                                         half_line, half_line)),
    strip.text.x          = NULL,
    strip.text.y          = element_text(angle = -90),
    strip.placement       = "inside",
    strip.placement.x     =  NULL,
    strip.placement.y     =  NULL,
    strip.switch.pad.grid = unit(0.1, "cm"),
    strip.switch.pad.wrap = unit(0.1, "cm"),

    #These affect the plot area itself (not around the axes)
    plot.background = element_rect(fill = "white"),
    plot.title      = element_text(size = rel(1.3), hjust = 0, vjust = 1,
                                   margin = margin(b = half_line * 0.75)),
    plot.subtitle   = element_text(size = rel(0.9), hjust = 0, vjust = 1,
                                   margin = margin(b = half_line * 1.5)),
    plot.caption    = element_text(size = rel(0.9), hjust = 1, vjust = 1,
                                   margin = margin(t = half_line * 2)),
    plot.margin     = margin(half_line, half_line, half_line, half_line),

    complete = TRUE
  )
}

#################################################################

#' Dark plotting theme
#'
#' @param base_size Font size.
#' @param base_family Font family.
#' @param base_line_size Line thickness. Relative to font size by default.
#' @param base_rect_size Rectangle line thickness. Relative to font size by default.
#' @param legend Location of legend. Can be removed ("none"), "bottom", "top", "left", "right".
#' @param tick_margins Distance between tick and text.
#'
#' @return ggplot theme
#' @export

theme_tidydark <- function(base_size = 12, base_family = "Arial Rounded MT Bold",
                            base_line_size = base_size / 20,
                            base_rect_size = base_size / 20,
                            tick_margins = 0.8, legend = "none") {

  if(!base_family %in% extrafont::fonts()){

    user_response <- menu(choices = c("Use default font", paste0("Load ", base_family)),
                          title = paste0("The font family ", base_family, " does not exist. What would you like to do?"))

    if(user_response == 1){

      base_family <- "Arial"

    } else {

      extrafont::font_import(pattern = base_family)

    }

  }

  half_line <- base_size / 2

  theme(
    # Elements in this first block aren't used directly, but are inherited
    # by others. These set the defaults for line, rectangle and text elements.
    line = element_line(colour = "white", size = base_line_size,
                        linetype = 1, lineend = "round"),
    rect = element_rect(fill = "#101010", colour = "black",
                        size = base_rect_size, linetype = 1),
    text = element_text(family = base_family, face = "plain",
                        colour = "white", size = base_size,
                        lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0,
                        margin = margin(), debug = FALSE),

    #These affect the ticks and tick text in all circumstances (e.g. top and bottom axis)
    axis.line         = element_line(size = 1, colour = "black"),
    axis.line.x       = NULL,
    axis.line.y       = NULL,
    axis.text         = element_text(size = rel(0.8), face = "bold"),
    axis.text.x       = element_text(margin = margin(t = tick_margins * half_line / 2), vjust = 1),
    axis.text.x.top   = element_text(margin = margin(b = tick_margins * half_line / 2), vjust = 0),
    axis.text.y       = element_text(margin = margin(r = tick_margins * half_line / 2), hjust = 1),
    axis.text.y.right = element_text(margin = margin(l = tick_margins * half_line / 2), hjust = 0),
    axis.ticks        = element_line(colour = "white", lineend = "round", size = ),
    axis.ticks.length = unit(half_line / 2, "pt"),

    #These affect the axis labels
    axis.title.x       = element_text(margin = margin(t = half_line * 1.5),
                                      vjust = 1, face = "bold"),
    axis.title.x.top   = element_text(margin = margin(b = half_line),
                                      vjust = 0, face = "bold"),
    axis.title.y       = element_text(angle = 90, margin = margin(r = half_line * 1.5),
                                      vjust = 0, face = "bold"),
    axis.title.y.right = element_text(angle = -90, margin = margin(l = half_line),
                                      vjust = 0, face = "bold"),

    #These affect plot legends
    legend.background     = element_blank(),
    legend.spacing        = unit(2 * half_line, "pt"),
    legend.spacing.x      = NULL,
    legend.spacing.y      = NULL,
    legend.margin         = margin(half_line, half_line, half_line, half_line),
    legend.key            = element_rect(fill = NA, colour = "#101010"),
    legend.key.size       = unit(1.2, "lines"),
    legend.key.width      = NULL,
    legend.key.height     = NULL,
    legend.text.align     = 0.5,
    legend.title.align    = 0.5,
    legend.direction      = "horizontal",
    legend.justification  = "center",
    legend.box            = "vertical",
    legend.box.margin     = margin(t = 1, r = 1, b = 1, l = 1, unit = "pt"),
    legend.box.background = element_blank(),
    legend.box.spacing    = unit(1, "cm"),
    legend.position       = legend,
    legend.text           = element_text(size = rel(0.8)),
    legend.title          = element_text(size = rel(1)),

    #These affect the background of the whole panel (plotting area and outside plotting area)
    panel.background = element_rect(fill = "#101010", colour = NA),
    panel.border     = element_blank(),
    panel.grid       = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.spacing    = unit(half_line, "pt"),
    panel.spacing.x  = NULL,
    panel.spacing.y  = NULL,
    panel.ontop      = FALSE,

    #These affect the plot headers if faceting
    strip.background      = element_rect(fill = NA, colour = "white"),
    strip.text            = element_text(size = rel(0.8),
                                         margin = margin(half_line, half_line,
                                                         half_line, half_line)),
    strip.text.x          = NULL,
    strip.text.y          = element_text(angle = -90),
    strip.placement       = "inside",
    strip.placement.x     = NULL,
    strip.placement.y     = NULL,
    strip.switch.pad.grid = unit(0.1, "cm"),
    strip.switch.pad.wrap = unit(0.1, "cm"),

    #These affect the plot area itself (not around the axes)
    plot.background   = element_rect(fill = "#101010"),
    plot.title        = element_text(size = rel(1.3), hjust = 0, vjust = 1,
                                     margin = margin(b = half_line * 0.75)),
    plot.subtitle     = element_text(size = rel(0.9), hjust = 0, vjust = 1,
                                     margin = margin(b = half_line * 1.5)),
    plot.caption      = element_text(size = rel(0.9), hjust = 1, vjust = 1,
                                     margin = margin(t = half_line * 2)),
    plot.margin       = margin(half_line, half_line, half_line, half_line),
    plot.tag          = NULL,
    plot.tag.position = NULL,

    complete = TRUE
  )
}
LiamDBailey/MyFuncs documentation built on June 5, 2019, 5:10 p.m.