| @@ -1,3 +1,4 @@ | |||
| ^LICENSE\.md$ | |||
| ^.*\.Rproj$ | |||
| ^\.Rproj\.user$ | |||
| R/extra\.R | |||
| @@ -1,5 +1,5 @@ | |||
| Package: ggpomological | |||
| Version: 0.0.0.9000 | |||
| Version: 0.1.0 | |||
| Title: Pomological plot themes for ggplot2 | |||
| Description: Pomological plot themes and scales for ggplot2 (in progress) | |||
| Authors@R: person("Garrick", "Aden-Buie", , "g.adenbuie@gmail.com", c("aut", "cre")) | |||
| @@ -9,3 +9,10 @@ LazyData: true | |||
| ByteCompile: true | |||
| URL: https://github.com/gadenbuie/ggpomological | |||
| BugReports: https://github.com/gadenbuie/ggpomological/issues | |||
| RoxygenNote: 6.0.1 | |||
| Roxygen: list(markdown = TRUE) | |||
| Depends: | |||
| ggplot2 | |||
| Imports: | |||
| magick, | |||
| extrafont | |||
| @@ -0,0 +1,9 @@ | |||
| # Generated by roxygen2: do not edit by hand | |||
| export(paint_pomological) | |||
| export(scale_color_pomological) | |||
| export(scale_colour_pomological) | |||
| export(scale_fill_pomological) | |||
| export(theme_pomological) | |||
| export(theme_pomological_nobg) | |||
| export(theme_pomological_plain) | |||
| @@ -0,0 +1,85 @@ | |||
| # # load all colors | |||
| # x <- readLines("pomological.css") | |||
| # x <- stringr::str_extract(x, "#[0-9a-f]{6}") | |||
| # x <- x[!is.na(x)] | |||
| # | |||
| # gg_color_hue <- function(n) { | |||
| # hues = seq(15, 375, length = n + 1) | |||
| # hcl(h = hues, l = 65, c = 100)[1:n] | |||
| # } | |||
| # | |||
| # col2hsv <- function(x) rgb2hsv(col2rgb(x)) | |||
| # | |||
| # | |||
| # dist2ref_color <- function(color, ref_color) { | |||
| # stopifnot(length(ref_color) == 1) | |||
| # x <- col2hsv(c(color, ref_color)) %>% | |||
| # t %>% | |||
| # dist %>% | |||
| # as.matrix %>% | |||
| # {tibble('ref_color' = .[length(color) + 1, 1:length(color)])} | |||
| # names(x) <- ref_color | |||
| # x | |||
| # } | |||
| # | |||
| # compare_to_ggplot <- function(compare_to_ggplot) { | |||
| # pomo_gg <- map_dfr(set_names(compare_to_ggplot), ~ as_tibble(t(col2hsv(.))), .id = "color") %>% | |||
| # bind_cols( | |||
| # map_dfc(gg_color_hue(set_names(length(compare_to_ggplot))), ~ dist2ref_color(compare_to_ggplot, .)) | |||
| # ) %>% | |||
| # tidyr::gather('ggplot_color', 'dist', -color:-v) %>% | |||
| # # group_by(color) %>% | |||
| # # do(dist = min(.$dist), ggplot_color = filter(., dist == min(.$dist))$ggplot_color) %>% | |||
| # # mutate(dist = map_dbl(dist, ~ .), ggplot_color = map_chr(ggplot_color, ~ .)) %>% | |||
| # # ungroup %>% | |||
| # mutate(ggplot_color = factor(ggplot_color, gg_color_hue(length(compare_to_ggplot)))) %>% | |||
| # arrange(ggplot_color) | |||
| # warning(glue::glue("Palette has {length(compare_to_ggplot)} colors"), call. = FALSE) | |||
| # ggplot(pomo_gg) + | |||
| # aes(x = ggplot_color, y = dist, fill = color, label = color) + | |||
| # geom_label(color = 'white')+ | |||
| # # geom_point(shape = 15, size = 5) + | |||
| # scale_fill_identity() | |||
| # } | |||
| # | |||
| # data_frame( | |||
| # 'color' = color_options, | |||
| # # 'group' = sample(c('pomo', 'logical'), length(color_options), replace = TRUE), | |||
| # 'x' = pmap_chr(tidyr::crossing(letters, letters), ~paste0(..1, ..2))[1:length(color_options)], | |||
| # 'y' = 1:length(color_options) | |||
| # ) %>% | |||
| # ggplot() + | |||
| # aes(x, y, fill = color) + | |||
| # # geom_point(size = 8)+ | |||
| # geom_col()+ | |||
| # geom_text(aes(label = color), hjust = -0.1) + | |||
| # scale_fill_identity() + | |||
| # coord_flip() + | |||
| # theme_minimal() + | |||
| # #theme_xkcd() + | |||
| # theme( | |||
| # text = element_text(family = 'gWriting', size = 16), | |||
| # plot.background = element_rect(fill = base_colors["paper_light"], color = NA), | |||
| # panel.grid = element_line(color = "#efe1c6"), | |||
| # axis.text = element_text(color = "#655843", size = 14) | |||
| # ) | |||
| # | |||
| # ordered_plot <- function(color_options, dichromat = FALSE) { | |||
| # if (dichromat) { | |||
| # dichr_type <- sample(c("deutan", "protan", "tritan"), 1) | |||
| # message(glue::glue("color blindness: {dichr_type}")) | |||
| # color_options <- dichromat::dichromat(color_options, dichr_type) | |||
| # } | |||
| # data_frame( | |||
| # color = color_options, | |||
| # x = 1, | |||
| # y = 1:length(color_options) | |||
| # ) %>% | |||
| # ggplot() + | |||
| # aes(x, y, fill = color, label = color) + | |||
| # geom_tile() + | |||
| # geom_label(color = 'white') + | |||
| # scale_fill_identity()+ | |||
| # scale_y_continuous(breaks = 1:length(color_options), labels = 1:length(color_options))+ | |||
| # theme_minimal() | |||
| # } | |||
| @@ -0,0 +1,8 @@ | |||
| #' A Pomological ggplot2 Theme | |||
| #' | |||
| #' This package provides a ggplot2 theme inspired by the | |||
| #' [USDA Pomological Watercolors collection](https://usdawatercolors.nal.usda.gov/pom) | |||
| #' and by Aron Atkins's ([\@aronatkins](https://twitter.com/aronatkins])) | |||
| #' [talk on parameterized RMarkdown](https://github.com/rstudio/rstudio-conf/tree/master/2018/Fruit_For_Thought--Aron_Atkins) | |||
| #' at [rstudio::conf 2018](https://www.rstudio.com/conference/). | |||
| "_PACKAGE" | |||
| @@ -0,0 +1,70 @@ | |||
| #' Paint a ggpomological watercolor | |||
| #' | |||
| #' Uses [magick] to paint a pomological watercolor. (Paints your plot onto a | |||
| #' pomological watercolor style paper, with texture overlay.) | |||
| #' | |||
| #' @references https://usdawatercolors.nal.usda.gov/pom | |||
| #' @seealso [theme_pomological] | |||
| #' @param pomo_gg A pomologically styled ggplot2 object. See [theme_pomological()] | |||
| #' @param width Width of output image in pixels | |||
| #' @param height Height of output image in pixels | |||
| #' @param pointsize Text size for plot text | |||
| #' @param outfile Optional name for output file if you'd like to save the image | |||
| #' @param pomological_background Paper image, defaults to paper texture provided | |||
| #' by ggpomological. | |||
| #' @param pomological_overlay Overlay texture. Set to `NULL` for no texture. | |||
| #' @inheritDotParams magick::image_graph res clip antialias | |||
| #' @export | |||
| paint_pomological <- function( | |||
| pomo_gg, | |||
| width = 800, | |||
| height = 500, | |||
| pointsize = 16, | |||
| outfile = NULL, | |||
| pomological_background = pomological_images("background"), | |||
| pomological_overlay = pomological_images("overlay"), | |||
| ... | |||
| ) { | |||
| if (!requireNamespace("magick", quietly = TRUE)) { | |||
| stop("The package magick is required for `paint_pomological()`. ", | |||
| "Please install with `install.packages('magick')`") | |||
| } | |||
| if (!file.exists(pomological_background)) { | |||
| warning(paste0("Cannot find file \"", pomological_background, "\""), call. = FALSE) | |||
| } | |||
| # Paint figure | |||
| pomo_gg <- pomo_gg + ggplot2::theme(plot.background = ggplot2::element_rect(fill = 'transparent', colour = NA)) | |||
| gg_fig <- magick::image_graph(width, height, bg = "transparent", pointsize = pointsize, ...) | |||
| print(pomo_gg) | |||
| dev.off() | |||
| if (!is.null(pomological_overlay) && file.exists(pomological_overlay)) { | |||
| pomo_over <- magick::image_read(pomological_overlay) | |||
| pomo_over <- magick::image_resize(pomo_over, paste0(width, "x", height, "!")) | |||
| gg_fig <- magick::image_composite(gg_fig, pomo_over, "blend", compose_args = "15") | |||
| } | |||
| # Paint background | |||
| if (file.exists(pomological_background)) { | |||
| pomo_bg <- magick::image_read(pomological_background) | |||
| pomo_bg <- magick::image_resize(pomo_bg, paste0(width, "x", height, "!")) | |||
| pomo_bg <- magick::image_crop(pomo_bg, paste0(width, "x", height)) | |||
| # Paint figure onto background | |||
| pomo_img <- magick::image_composite(pomo_bg, gg_fig) | |||
| } else pomo_img <- gg_fig | |||
| if (!is.null(outfile)) { | |||
| # Do you want your picture framed? | |||
| magick::image_write(pomo_img, outfile) | |||
| } | |||
| pomo_img | |||
| } | |||
| pomological_images <- function(which = c("background", "overlay")) { | |||
| which <- match.arg(which) | |||
| exts <- c("background" = ".png", "overlay" = ".jpg") | |||
| system.file("images", paste0("pomological_", which, exts[which]), | |||
| package = "ggpomological") | |||
| } | |||
| @@ -0,0 +1,45 @@ | |||
| pomological_palette <- c( | |||
| "#c03728" #red | |||
| ,"#919c4c" #green darkish | |||
| ,"#fd8f24" #orange brighter | |||
| ,"#f5c04a" #yelloww | |||
| ,"#e68c7c" #pink | |||
| ,"#828585" #light grey | |||
| ,"#c3c377" #green light | |||
| ,"#4f5157" #darker blue/grey | |||
| ,"#6f5438" #lighter brown | |||
| ) | |||
| pomological_base <- list( | |||
| "paper" = "#fffeea", | |||
| "paper_alt" = "#f8eed1", | |||
| "light_line" = "#efe1c6", | |||
| "medium_line" = "#a89985", | |||
| "darker_line" = "#6b452b", | |||
| "black" = "#3a3e3f", | |||
| "dark_blue" = "#2b323f" | |||
| ) | |||
| #' Pomological Color and Fill Scales | |||
| #' | |||
| #' Color scales based on the USDA Pomological Watercolors paintings. | |||
| #' | |||
| #' @references https://usdawatercolors.nal.usda.gov/pom | |||
| #' @seealso [ggplot2::scale_colour_discrete] [ggplot2::scale_fill_discrete] | |||
| #' @inheritDotParams ggplot2::discrete_scale | |||
| #' @name scale_pomological | |||
| NULL | |||
| pomological_pal <- function() scales::manual_pal(pomological_palette) | |||
| #' @rdname scale_pomological | |||
| #' @export | |||
| scale_colour_pomological <- function(...) ggplot2::discrete_scale("colour", "pomological", pomological_pal(), ...) | |||
| #' @rdname scale_pomological | |||
| #' @export | |||
| scale_color_pomological <- scale_colour_pomological | |||
| #' @rdname scale_pomological | |||
| #' @export | |||
| scale_fill_pomological <- function(...) ggplot2::discrete_scale('fill', 'pomological', pomological_pal(), ...) | |||
| @@ -0,0 +1,157 @@ | |||
| #' Pomological Theme | |||
| #' | |||
| #' [ggplot2] plot theme based on the USDA Pomological Watercolors paintings. | |||
| #' | |||
| #' @references https://usdawatercolors.nal.usda.gov/pom | |||
| #' @seealso [ggplot2::theme] | |||
| #' @param base_family Base text family. See **Fonts** in [theme_pomological()] | |||
| #' for some examples from Google Fonts options, including `"Mr De Haviland"`, | |||
| #' `"Homemade Apple"`, `"Marck Script"`, and `"Mr. Bedfort"`. For the | |||
| #' authentic pomological look, use `"Homemade Apple"` or `"Mr De Haviland"`. | |||
| #' Set to `NULL` or use [theme_pomological_plain()] for no change to fonts. | |||
| #' @param base_size Base text size | |||
| #' @param text.color Color of all text (except axis text, see `axis.text.color`) | |||
| #' @param plot.background.color Color of plot background, passed to `plot.background` | |||
| #' @param panel.border.color Color of plot panel border | |||
| #' @param with.panel.grid If `FALSE` gridlines in plot are removed | |||
| #' @param panel.grid.color,panel.grid.linetype Color and linetype of panel grid, passed to `panel.grid` | |||
| #' @param axis.text.color,axis.text.size Color and size of axis text | |||
| #' @param base_theme Starting theme of plot, default is | |||
| #' [ggplot2::theme_minimal()]. Any elements set by `theme_pomological()` will | |||
| #' overwrite the `base_theme` unless the specific parameter is explicitly set | |||
| #' to `NULL`. | |||
| #' | |||
| #' @section Fonts: | |||
| #' Complete the pomological watercolor theme with a handwriting or cursive font. | |||
| #' The following fonts from [Google Fonts](https://fonts.google.com) work well. | |||
| #' Visit the links below to install on your system. | |||
| #' | |||
| #' - [Homemade Apple](https://fonts.google.com/specimen/Homemade+Apple/) | |||
| #' - [Mr. De Haviland](https://fonts.google.com/specimen/Mr+De+Haviland) | |||
| #' - [Marck Script](https://fonts.google.com/specimen/Marck+Script/) | |||
| #' - [Mr. Bedfort](https://fonts.google.com/specimen/Mr+Bedfort/) | |||
| #' | |||
| #' Fonts with R are notoriously tricky, so these may not work well for you. If | |||
| #' you have installed the fonts but they aren't showing up or working, you can | |||
| #' always try running `extrafont::font_import()` or `extrafont::load_fonts()` in | |||
| #' the session or RMarkdown document. Or you can use [theme_pomological_plain()]. | |||
| #' | |||
| #' @examples | |||
| #' library(ggplot2) | |||
| #' basic_iris_plot <- ggplot(iris) + | |||
| #' aes(x = Sepal.Length, y = Sepal.Width, color = Species) + | |||
| #' geom_point(size = 2) + | |||
| #' # with pomological color scale | |||
| #' scale_color_pomological() | |||
| #' | |||
| #' # Pomological Theme | |||
| #' basic_iris_plot + | |||
| #' theme_pomological() | |||
| #' | |||
| #' # Don't change panel grid color | |||
| #' basic_iris_plot + | |||
| #' theme_pomological( | |||
| #' panel.grid.color = NULL | |||
| #' ) | |||
| #' | |||
| #' # White background | |||
| #' basic_iris_plot + | |||
| #' theme_pomological_nobg() | |||
| #' | |||
| #' # Plain plot without font or background | |||
| #' basic_iris_plot + | |||
| #' theme_pomological_plain() | |||
| #' | |||
| #' @export | |||
| theme_pomological <- function( | |||
| base_family = "Homemade Apple", | |||
| base_size = 14, | |||
| text.color = pomological_base$dark_blue, | |||
| plot.background.color = pomological_base$paper, | |||
| panel.border.color = pomological_base$light_line, | |||
| with.panel.grid = FALSE, | |||
| panel.grid.color = pomological_base$light_line, | |||
| panel.grid.linetype = "dashed", | |||
| axis.text.color = pomological_base$medium_line, | |||
| axis.text.size = base_size * 3/4, | |||
| base_theme = ggplot2::theme_minimal() | |||
| ) { | |||
| if (!is.null(base_family)) check_font(base_family) | |||
| base_theme + | |||
| ggplot2::theme( | |||
| text = ggplot2::element_text( | |||
| family = base_family, | |||
| size = base_size, | |||
| colour = text.color | |||
| ), | |||
| plot.background = ggplot2::element_rect( | |||
| fill = plot.background.color, | |||
| colour = NA | |||
| ), | |||
| panel.grid = ggplot2::element_line( | |||
| colour = panel.grid.color, | |||
| linetype = panel.grid.linetype), | |||
| panel.border = ggplot2::element_rect( | |||
| color = panel.border.color, | |||
| fill = NA, | |||
| linetype = "solid", | |||
| size = 0.75 | |||
| ), | |||
| panel.grid.major = if (!with.panel.grid) ggplot2::element_blank(), | |||
| panel.grid.minor = ggplot2::element_blank(), | |||
| axis.text = ggplot2::element_text( | |||
| colour = axis.text.color, | |||
| size = axis.text.size) | |||
| ) | |||
| } | |||
| #' @describeIn theme_pomological Pomological theme with white (transparent) background | |||
| #' @export | |||
| theme_pomological_nobg <- function(...) { | |||
| dots <- list(...) | |||
| dots$plot.background.color <- "transparent" | |||
| do.call("theme_pomological", args = dots) | |||
| } | |||
| #' @describeIn theme_pomological A "plain" pomological theme with white | |||
| #' background and normal fonts. | |||
| #' @export | |||
| theme_pomological_plain <- function(...) { | |||
| dots <- list(...) | |||
| dots$plot.background.color <- "transparent" | |||
| if (!"base_family" %in% names(dots)) dots["base_family"] <- "" | |||
| if (!"base_size" %in% names(dots)) dots["base_size"] <- 11 | |||
| do.call("theme_pomological", args = dots) | |||
| } | |||
| font_urls <- data.frame( | |||
| name = c("Mr De Haviland", "Homemade Apple", "Marck Script", "Mr. Bedfort"), | |||
| url = c( | |||
| "https://fonts.google.com/specimen/Mr+De+Haviland", | |||
| "https://fonts.google.com/specimen/Homemade+Apple/", | |||
| "https://fonts.google.com/specimen/Marck+Script/", | |||
| "https://fonts.google.com/specimen/Mr+Bedfort/" | |||
| ) | |||
| ) | |||
| check_font <- function(font_name) { | |||
| if (!requireNamespace("extrafont", quietly = TRUE)) { | |||
| warning("The font \"", font_name, "\" may or may not be installed on your system.", | |||
| "Please install the package `extrafont` if you'd like me to be able to check for you.", | |||
| call. = FALSE) | |||
| } else { | |||
| if (!font_name %in% extrafont::fonts()) { | |||
| if (font_name %in% font_urls$name) { | |||
| warning("Font '", font_name, "' isn't in the extrafonts font list (but it may still work). ", | |||
| "If recently installed, you can try running `extrafonts::font_import()`. ", | |||
| "To install, visit: ", font_urls[font_urls$name == font_name, "url"], | |||
| call. = FALSE) | |||
| } else { | |||
| warning("Font '", font_name, "' isn't in the extrafonts font list (but it may still work). ", | |||
| "If recently installed, you can try running `extrafonts::font_import()`. ", | |||
| call. = FALSE) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -9,23 +9,12 @@ editor_options: | |||
| ```{r setup, include=FALSE} | |||
| knitr::opts_chunk$set(echo = TRUE, fig.width=8, fig.height=5) | |||
| library(ggpomological) | |||
| library(dplyr) | |||
| ``` | |||
| ## Pomological Plots | |||
|  | |||
| - [Pomological Plots](#pomological-plots) | |||
| - [Color Palette](#color-palette) | |||
| - [Setup theme and scales](#setup-theme-and-scales) | |||
| - [Add paper background!](#add-paper-background) | |||
| - [Demo!](#demo) | |||
| - [Basic iris plot](#basic-iris-plot) | |||
| - [Stacked bar chart](#stacked-bar-chart) | |||
| - [Density Plot](#density-plot) | |||
| - [Points and lines](#points-and-lines) | |||
| - [One last plot](#one-last-plot) | |||
| - [Appendix](#appendix) | |||
| <!-- Links --> | |||
| [rstudioconf]: https://www.rstudio.com/conference/ | |||
| @@ -36,212 +25,82 @@ knitr::opts_chunk$set(echo = TRUE, fig.width=8, fig.height=5) | |||
| [t-pomological]: https://twitter.com/pomological | |||
| [magick]: https://cran.r-project.org/web/packages/magick/index.html | |||
| Aron Atkins ([\@aronatkins][t-aronatkins]) gave a great talk at [rstudio::conf 2018][rstudioconf] about a subject near and dear to my heart: parameterized RMarkdown. | |||
| And apples. | |||
| In his talk, he designed a parameterized RMarkdown report that would provide the user with a customized report for their selected fruit, based on the [USDA Pomological Watercolors database][usda-pom]. | |||
| I hade never heard of the USDA watercolor -- or the it's fan club twitter account [\@pomological][t-pomological] until watching his talk. | |||
| It's a treasure trove of thousands of watercolor images of fruits; beautiful images with intricate details and a very unique and stunning palette. | |||
| The perfect palette for a custom ggplot2 theme. | |||
| This package provides a ggplot2 theme inspired by the [USDA Pomological Watercolors collection][usda-pom] and by Aron Atkins's ([\@aronatkins][t-aronatkins]) [talk on parameterized RMarkdown][rsconf-video] at [rstudio::conf 2018][rstudioconf]. | |||
| What follows is a set of functions that I plan to pull together into a simple package that will provide a custom, pomological-inspired ggplot2 theme. | |||
|  | |||
| Before reading more about `ggpomological`, you should really check out [Aron's talk][rsconf-video] or [his slides][rsconf-slides]. | |||
|  | |||
| ## Color Palette | |||
| ## Installation | |||
| The first thing I did was browse through the [pomological watercolors collection][usda-pom], downloading images of a wide variety of fruits. | |||
| I didn't do this in any systematic way, other than occasionally searching for a particular type of fruit, like 'grape' or 'papaya'. | |||
| This package isn't on CRAN, so you'll need to use the devtools package to install it. | |||
| From these images, I used an application (that I installed forever ago and is no longer around) called ColorSchemer Studio to pull out a set of colors that I felt represented the collection. | |||
| ```r | |||
| # If you don't have devtools installed | |||
| install.packages("devtools") | |||
| I ended up with a lot of colors. | |||
| devtools::install_github("gadenbuie/ggpomological") | |||
| ``` | |||
|  | |||
| ## Color Palette | |||
| From this list, I chose just a few that worked well together. | |||
| The colors for this theme were drawn from many images from the [USDA Pomological Watercolors collection][usda-pom], I chose just a few that I thought worked well together for color and fill scales | |||
| ```{r} | |||
| pomological_palette <- c( | |||
| "#c03728" #red | |||
| ,"#919c4c" #green darkish | |||
| ,"#fd8f24" #orange brighter | |||
| ,"#f5c04a" #yelloww | |||
| ,"#e68c7c" #pink | |||
| ,"#828585" #light grey | |||
| ,"#c3c377" #green light | |||
| ,"#4f5157" #darker blue/grey | |||
| ,"#6f5438" #lighter brown | |||
| ) | |||
| # Palette colors | |||
| scales::show_col(pomological_palette) | |||
| pomological_base <- list( | |||
| "paper" = "#fffeea" | |||
| ,"paper_alt" = "#f8eed1" | |||
| ,"light_line" = "#efe1c6" | |||
| ,"medium_line" = "#a89985" | |||
| ,"darker_line" = "#6b452b" | |||
| ,"black" = "#3a3e3f" | |||
| ,"dark_blue" = "#2b323f" | |||
| ) | |||
| # Base colors | |||
| scales::show_col(unlist(pomological_base)) | |||
| scales::show_col(ggpomological:::pomological_palette) | |||
| ``` | |||
| and a few colors for the plot background and decoration | |||
| ## Setup theme and scales | |||
| I created two theme-generating functions, `pomological_theme()` sets the plot theme to be representative of the paper and styling of the watercolors and includes a paper-colored background, and `pomological_theme_nobg()` is the same as the first, just with a transparent (or white) background. | |||
| ```{r} | |||
| scales::show_col(unlist(ggpomological:::pomological_base)) | |||
| ``` | |||
| A handwriting font is needed for the fully authentic pomological look, and I found a few from Google Fonts that fit the bill. | |||
| I've also included a [css file](inst/pomological.css) with the complete collection of color samples. | |||
| - [Homemade Apple](https://fonts.google.com/specimen/Homemade+Apple/) | |||
| - [Amatic SC](https://fonts.google.com/specimen/Amatic+SC/) | |||
| - [Mr. Bedfort](https://fonts.google.com/specimen/Mr+Bedfort/) | |||
| Alternatively, use something like [calligrapher.com](https://www.calligraphr.com/) to create your own handwriting font! | |||
| ## Setup theme and scales | |||
| ```{r pomological-theme} | |||
| pomological_theme <- function( | |||
| base_family = 'Homemade Apple', | |||
| base_size = 16, | |||
| text.color = NULL, | |||
| plot.background.color = NULL, | |||
| panel.grid.color = NULL, | |||
| panel.grid.linetype = 'dashed', | |||
| axis.text.color = NULL, | |||
| axis.text.size = base_size * 14/16, | |||
| base_theme = ggplot2::theme_minimal() | |||
| ) { | |||
| pomological_base <- list( | |||
| "paper" = "#fffeea", | |||
| 'paper_alt' = "#f8eed1", | |||
| 'light_line' = '#efe1c6', | |||
| 'medium_line' = "#a89985", | |||
| 'darker_line' = "#6b452b", | |||
| 'black' = "#3a3e3f", | |||
| "dark_blue" = "#2b323f" | |||
| ) | |||
| base_theme + | |||
| ggplot2::theme( | |||
| text = element_text( | |||
| family = base_family, | |||
| size = base_size, | |||
| colour = ifelse(hasArg(text.color), text.color, pomological_base$dark_blue) | |||
| ), | |||
| plot.background = element_rect( | |||
| fill = ifelse(hasArg(plot.background.color), plot.background.color, pomological_base$paper), | |||
| colour = NA | |||
| ), | |||
| panel.grid = element_line( | |||
| colour = ifelse(hasArg(panel.grid.color), panel.grid.color, pomological_base$light_line), | |||
| linetype = panel.grid.linetype), | |||
| panel.grid.major = element_line( | |||
| colour = ifelse(hasArg(panel.grid.color), panel.grid.color, pomological_base$light_line), | |||
| linetype = panel.grid.linetype), | |||
| panel.grid.minor = element_blank(), | |||
| axis.text = element_text( | |||
| colour = ifelse(hasArg(axis.text.color), axis.text.color, pomological_base$medium_line), | |||
| size = axis.text.size) | |||
| ) | |||
| } | |||
| pomological_theme_nobg <- function(...) { | |||
| dots <- list(...) | |||
| dots$plot.background.color <- 'transparent' | |||
| do.call('pomological_theme', args = dots) | |||
| } | |||
| ``` | |||
| There are three theme-generating functions: | |||
| - `theme_pomological()` sets the plot theme to be representative of the paper and styling of the watercolors and includes a paper-colored background, | |||
| Here are the color scales you'll need: `scale_color_pomological` and `scale_fill_pomological`. | |||
| - `theme_pomological_nobg()` has the same styling, just with a transparent (or white) background, | |||
| - `theme_pomological_plain()` has a white background and doesn't change the font unless requested. | |||
| ```{r pomological-scales} | |||
| # learned this from https://github.com/hrbrmstr/hrbrthemes/blob/13f9b59579f007b8a5cbe5c699cbe3ec5fdd28a1/R/color.r | |||
| pomological_pal <- function() scales::manual_pal(pomological_palette) | |||
| A handwriting font is needed for the fully authentic pomological look, and I found a few from Google Fonts that fit the bill. | |||
| # Scale color | |||
| scale_colour_pomological <- function(...) ggplot2::discrete_scale("colour", "pomological", pomological_pal(), ...) | |||
| scale_color_pomological <- scale_colour_pomological | |||
| - [Mr. De Haviland](https://fonts.google.com/specimen/Mr+De+Haviland) | |||
| - [Homemade Apple](https://fonts.google.com/specimen/Homemade+Apple/) | |||
| - [Marck Script](https://fonts.google.com/specimen/Marck+Script/) | |||
| - [Mr. Bedfort](https://fonts.google.com/specimen/Mr+Bedfort/) | |||
| # Scale fill | |||
| scale_fill_pomological <- function(...) ggplot2::discrete_scale('fill', 'pomological', pomological_pal(), ...) | |||
| ``` | |||
| Alternatively, use something like [calligrapher.com](https://www.calligraphr.com/) to create your own handwriting font! | |||
| For color and fill scales, **ggpomological** provides `scale_color_pomological()` and `scale_fill_pomological()`. | |||
| In the future, I might come back to this to | |||
| In the future, I might revisit this package to | |||
| 1. Increase colors in discrete scale | |||
| 2. Setup a color-pairs plot. Lots of great color pairs in the extracted colors. | |||
| 2. Setup paired color scales. Lots of great color pairs in the extracted colors. | |||
| 3. Set up continuous scale colors (we'll see...) | |||
| ## Add paper background! | |||
| Great, but I want my plots to look even more pomological, you say? | |||
| Perfect! | |||
| This function uses the [`magick`][magick] package to add a pomological watercolor paper background and a subtle texture overlay. | |||
| ```{r paint_pomological} | |||
| paint_pomological <- function( | |||
| pomo_gg, | |||
| width = 800, | |||
| height = 500, | |||
| pointsize = 16, | |||
| pomological_background = 'pomological_bg.png', | |||
| pomological_overlay = "pomological_overlay.jpg", | |||
| outfile = NULL, | |||
| ... | |||
| ) { | |||
| requireNamespace('magick', quietly = TRUE) | |||
| requireNamespace('glue', quietly = TRUE) | |||
| if (!file.exists(pomological_background)) { | |||
| warning(glue::glue("Cannot find file \"{pomological_background}\", so you can have your plot back!")) | |||
| return(pomo_gg) | |||
| } | |||
| # Paint figure | |||
| gg_fig <- magick::image_graph(width, height, bg = 'transparent', pointsize = pointsize, ...) | |||
| print(pomo_gg) | |||
| dev.off() | |||
| if (!is.null(pomological_overlay) && file.exists(pomological_overlay)) { | |||
| pomo_over <- magick::image_read(pomological_overlay) | |||
| pomo_over <- magick::image_resize(pomo_over, glue::glue("{width}x{height}!")) | |||
| gg_fig <- magick::image_composite(gg_fig, pomo_over, "blend", compose_args = "15") | |||
| } | |||
| # Paint background | |||
| pomo_bg <- magick::image_read(pomological_background) | |||
| pomo_bg <- magick::image_resize(pomo_bg, glue::glue("{width}x{height}!")) | |||
| pomo_bg <- magick::image_crop(pomo_bg, glue::glue("{width}x{height}")) | |||
| # Paint figure onto background | |||
| pomo_img <- magick::image_composite(pomo_bg, gg_fig) | |||
| if (!is.null(outfile)) { | |||
| # Do you want your picture framed? | |||
| magick::image_write(pomo_img, outfile) | |||
| } | |||
| pomo_img | |||
| } | |||
| ``` | |||
| **ggpomological** also provides a function named `paint_pomological` that uses the [`magick`][magick] package to add a pomological watercolor paper background and a subtle texture overlay. | |||
| ## Demo! | |||
| We'll need dplyr and ggplot2 | |||
| We'll need ggplot2 (loaded with **ggpomological**) and dplyr | |||
| ```{r libraries, messages=FALSE, warning=FALSE} | |||
| ```r | |||
| library(ggpomological) | |||
| library(dplyr) | |||
| library(ggplot2) | |||
| ``` | |||
| ### Basic iris plot | |||
| @@ -255,17 +114,19 @@ basic_iris_plot <- ggplot(iris) + | |||
| # Just your standard Iris plot | |||
| basic_iris_plot | |||
| # With pomological theme | |||
| basic_iris_plot + | |||
| pomological_theme() + | |||
| scale_color_pomological() | |||
| # With pomological colors | |||
| basic_iris_plot <- basic_iris_plot + scale_color_pomological() | |||
| basic_iris_plot | |||
| # With pomological theme | |||
| pomological_iris <- basic_iris_plot + theme_pomological() | |||
| pomological_iris | |||
| # With transparent background | |||
| pomological_iris <- basic_iris_plot + | |||
| pomological_theme_nobg() + | |||
| scale_color_pomological() | |||
| pomological_iris | |||
| basic_iris_plot + theme_pomological_nobg() | |||
| # Or with "plain" pomological | |||
| basic_iris_plot + theme_pomological_plain() | |||
| # Painted! | |||
| paint_pomological(pomological_iris, res = 110) %>% | |||
| @@ -283,13 +144,14 @@ stacked_bar_plot <- ggplot(diamonds) + | |||
| geom_histogram(binwidth = 850) + | |||
| xlab('Price (USD)') + | |||
| ylab('Count') + | |||
| ggtitle("ggpomological") + | |||
| scale_x_continuous(label = scales::dollar_format()) + | |||
| scale_fill_pomological() | |||
| stacked_bar_plot + pomological_theme() | |||
| stacked_bar_plot + theme_pomological() | |||
| paint_pomological( | |||
| stacked_bar_plot + pomological_theme_nobg(), | |||
| stacked_bar_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-bar-chart-painted.png") | |||
| @@ -309,10 +171,10 @@ density_plot <- mtcars %>% | |||
| scale_color_pomological() + | |||
| scale_fill_pomological() | |||
| density_plot + pomological_theme() | |||
| density_plot + theme_pomological() | |||
| paint_pomological( | |||
| density_plot + pomological_theme_nobg(), | |||
| density_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-density-demo-painted.png") | |||
| @@ -330,7 +192,7 @@ big_volume_cities <- txhousing %>% | |||
| group_by(city) %>% | |||
| summarize(mean_volume = mean(volume, na.rm = TRUE)) %>% | |||
| arrange(-mean_volume) %>% | |||
| top_n(length(pomological_palette)) %>% | |||
| top_n(length(ggpomological:::pomological_palette)) %>% | |||
| pull(city) | |||
| full_bar_stack_plot <- txhousing %>% | |||
| @@ -346,10 +208,10 @@ full_bar_stack_plot <- txhousing %>% | |||
| theme(panel.grid.minor.x = element_blank()) + | |||
| scale_fill_pomological() | |||
| full_bar_stack_plot + pomological_theme() | |||
| full_bar_stack_plot + theme_pomological() | |||
| paint_pomological( | |||
| full_bar_stack_plot + pomological_theme_nobg(), | |||
| full_bar_stack_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-full-bar-stack-painted.png") | |||
| @@ -359,13 +221,13 @@ paint_pomological( | |||
| ### One last plot | |||
| (in my handwriting) | |||
| Using my own handwriting and the `ggridges` package. | |||
| ```{r plot-ridges} | |||
| ridges_pomological <- ggplot(diamonds) + | |||
| aes(x = carat, y = clarity, color = clarity, fill = clarity) + | |||
| ggridges::geom_density_ridges(alpha = 0.75) + | |||
| pomological_theme_nobg( | |||
| theme_pomological_nobg( | |||
| base_family = 'gWriting', | |||
| base_size = 20, | |||
| base_theme = ggridges::theme_ridges() | |||
| @@ -378,100 +240,3 @@ paint_pomological(ridges_pomological, res = 110) %>% | |||
| ``` | |||
|  | |||
| ## Appendix | |||
| <details> | |||
| <summary>Some functions I wrote while exploring colors, that may or may not work here.</summary> | |||
| ```{r appendix, eval=FALSE} | |||
| # load all colors | |||
| x <- readLines("pomological.css") | |||
| x <- stringr::str_extract(x, "#[0-9a-f]{6}") | |||
| x <- x[!is.na(x)] | |||
| gg_color_hue <- function(n) { | |||
| hues = seq(15, 375, length = n + 1) | |||
| hcl(h = hues, l = 65, c = 100)[1:n] | |||
| } | |||
| col2hsv <- function(x) rgb2hsv(col2rgb(x)) | |||
| dist2ref_color <- function(color, ref_color) { | |||
| stopifnot(length(ref_color) == 1) | |||
| x <- col2hsv(c(color, ref_color)) %>% | |||
| t %>% | |||
| dist %>% | |||
| as.matrix %>% | |||
| {tibble('ref_color' = .[length(color) + 1, 1:length(color)])} | |||
| names(x) <- ref_color | |||
| x | |||
| } | |||
| compare_to_ggplot <- function(compare_to_ggplot) { | |||
| pomo_gg <- map_dfr(set_names(compare_to_ggplot), ~ as_tibble(t(col2hsv(.))), .id = "color") %>% | |||
| bind_cols( | |||
| map_dfc(gg_color_hue(set_names(length(compare_to_ggplot))), ~ dist2ref_color(compare_to_ggplot, .)) | |||
| ) %>% | |||
| tidyr::gather('ggplot_color', 'dist', -color:-v) %>% | |||
| # group_by(color) %>% | |||
| # do(dist = min(.$dist), ggplot_color = filter(., dist == min(.$dist))$ggplot_color) %>% | |||
| # mutate(dist = map_dbl(dist, ~ .), ggplot_color = map_chr(ggplot_color, ~ .)) %>% | |||
| # ungroup %>% | |||
| mutate(ggplot_color = factor(ggplot_color, gg_color_hue(length(compare_to_ggplot)))) %>% | |||
| arrange(ggplot_color) | |||
| warning(glue::glue("Palette has {length(compare_to_ggplot)} colors"), call. = FALSE) | |||
| ggplot(pomo_gg) + | |||
| aes(x = ggplot_color, y = dist, fill = color, label = color) + | |||
| geom_label(color = 'white')+ | |||
| # geom_point(shape = 15, size = 5) + | |||
| scale_fill_identity() | |||
| } | |||
| data_frame( | |||
| 'color' = color_options, | |||
| # 'group' = sample(c('pomo', 'logical'), length(color_options), replace = TRUE), | |||
| 'x' = pmap_chr(tidyr::crossing(letters, letters), ~paste0(..1, ..2))[1:length(color_options)], | |||
| 'y' = 1:length(color_options) | |||
| ) %>% | |||
| ggplot() + | |||
| aes(x, y, fill = color) + | |||
| # geom_point(size = 8)+ | |||
| geom_col()+ | |||
| geom_text(aes(label = color), hjust = -0.1) + | |||
| scale_fill_identity() + | |||
| coord_flip() + | |||
| theme_minimal() + | |||
| #theme_xkcd() + | |||
| theme( | |||
| text = element_text(family = 'gWriting', size = 16), | |||
| plot.background = element_rect(fill = base_colors["paper_light"], color = NA), | |||
| panel.grid = element_line(color = "#efe1c6"), | |||
| axis.text = element_text(color = "#655843", size = 14) | |||
| ) | |||
| ordered_plot <- function(color_options, dichromat = FALSE) { | |||
| if (dichromat) { | |||
| dichr_type <- sample(c("deutan", "protan", "tritan"), 1) | |||
| message(glue::glue("color blindness: {dichr_type}")) | |||
| color_options <- dichromat::dichromat(color_options, dichr_type) | |||
| } | |||
| data_frame( | |||
| color = color_options, | |||
| x = 1, | |||
| y = 1:length(color_options) | |||
| ) %>% | |||
| ggplot() + | |||
| aes(x, y, fill = color, label = color) + | |||
| geom_tile() + | |||
| geom_label(color = 'white') + | |||
| scale_fill_identity()+ | |||
| scale_y_continuous(breaks = 1:length(color_options), labels = 1:length(color_options))+ | |||
| theme_minimal() | |||
| } | |||
| ``` | |||
| </details> | |||
| @@ -5,269 +5,107 @@ Garrick Aden-Buie | |||
| ## Pomological Plots | |||
|  | |||
| - [Pomological Plots](#pomological-plots) | |||
| - [Color Palette](#color-palette) | |||
| - [Setup theme and scales](#setup-theme-and-scales) | |||
| - [Add paper background\!](#add-paper-background) | |||
| - [Demo\!](#demo) | |||
| - [Basic iris plot](#basic-iris-plot) | |||
| - [Stacked bar chart](#stacked-bar-chart) | |||
| - [Density Plot](#density-plot) | |||
| - [Points and lines](#points-and-lines) | |||
| - [One last plot](#one-last-plot) | |||
| - [Appendix](#appendix) | |||
| <!-- Links --> | |||
| Aron Atkins ([@aronatkins](https://twitter.com/aronatkins)) gave a great | |||
| talk at [rstudio::conf 2018](https://www.rstudio.com/conference/) about | |||
| a subject near and dear to my heart: parameterized RMarkdown. And | |||
| apples. | |||
| In his talk, he designed a parameterized RMarkdown report that would | |||
| provide the user with a customized report for their selected fruit, | |||
| based on the [USDA Pomological Watercolors | |||
| database](https://usdawatercolors.nal.usda.gov/pom). I hade never heard | |||
| of the USDA watercolor – or the it’s fan club twitter account | |||
| [@pomological](https://twitter.com/pomological) until watching his talk. | |||
| It’s a treasure trove of thousands of watercolor images of fruits; | |||
| beautiful images with intricate details and a very unique and stunning | |||
| palette. The perfect palette for a custom ggplot2 theme. | |||
| What follows is a set of functions that I plan to pull together into a | |||
| simple package that will provide a custom, pomological-inspired ggplot2 | |||
| theme. | |||
| Before reading more about `ggpomological`, you should really check out | |||
| [Aron’s talk](https://youtu.be/Ol1FjFR2IMU?t=5h21m15s) or [his | |||
| slides](https://github.com/rstudio/rstudio-conf/tree/master/2018/Fruit_For_Thought--Aron_Atkins). | |||
| This package provides a ggplot2 theme inspired by the [USDA Pomological | |||
| Watercolors collection](https://usdawatercolors.nal.usda.gov/pom) and by | |||
| Aron Atkins’s ([@aronatkins](https://twitter.com/aronatkins)) [talk on | |||
| parameterized RMarkdown](https://youtu.be/Ol1FjFR2IMU?t=5h21m15s) at | |||
| [rstudio::conf 2018](https://www.rstudio.com/conference/). | |||
| ## Color Palette | |||
|  | |||
|  | |||
| The first thing I did was browse through the [pomological watercolors | |||
| collection](https://usdawatercolors.nal.usda.gov/pom), downloading | |||
| images of a wide variety of fruits. I didn’t do this in any systematic | |||
| way, other than occasionally searching for a particular type of fruit, | |||
| like ‘grape’ or ‘papaya’. | |||
| ## Installation | |||
| From these images, I used an application (that I installed forever ago | |||
| and is no longer around) called ColorSchemer Studio to pull out a set of | |||
| colors that I felt represented the collection. | |||
| This package isn’t on CRAN, so you’ll need to use the devtools package | |||
| to install it. | |||
| I ended up with a lot of colors. | |||
| ``` r | |||
| # If you don't have devtools installed | |||
| install.packages("devtools") | |||
| devtools::install_github("gadenbuie/ggpomological") | |||
| ``` | |||
|  | |||
| ## Color Palette | |||
| From this list, I chose just a few that worked well together. | |||
| The colors for this theme were drawn from many images from the [USDA | |||
| Pomological Watercolors | |||
| collection](https://usdawatercolors.nal.usda.gov/pom), I chose just a | |||
| few that I thought worked well together for color and fill scales | |||
| ``` r | |||
| pomological_palette <- c( | |||
| "#c03728" #red | |||
| ,"#919c4c" #green darkish | |||
| ,"#fd8f24" #orange brighter | |||
| ,"#f5c04a" #yelloww | |||
| ,"#e68c7c" #pink | |||
| ,"#828585" #light grey | |||
| ,"#c3c377" #green light | |||
| ,"#4f5157" #darker blue/grey | |||
| ,"#6f5438" #lighter brown | |||
| ) | |||
| # Palette colors | |||
| scales::show_col(pomological_palette) | |||
| scales::show_col(ggpomological:::pomological_palette) | |||
| ``` | |||
| <!-- --> | |||
| and a few colors for the plot background and decoration | |||
| ``` r | |||
| pomological_base <- list( | |||
| "paper" = "#fffeea" | |||
| ,"paper_alt" = "#f8eed1" | |||
| ,"light_line" = "#efe1c6" | |||
| ,"medium_line" = "#a89985" | |||
| ,"darker_line" = "#6b452b" | |||
| ,"black" = "#3a3e3f" | |||
| ,"dark_blue" = "#2b323f" | |||
| ) | |||
| # Base colors | |||
| scales::show_col(unlist(pomological_base)) | |||
| scales::show_col(unlist(ggpomological:::pomological_base)) | |||
| ``` | |||
| <!-- --> | |||
| <!-- --> | |||
| I’ve also included a [css file](inst/pomological.css) with the complete | |||
| collection of color samples. | |||
| ## Setup theme and scales | |||
| I created two theme-generating functions, `pomological_theme()` sets the | |||
| plot theme to be representative of the paper and styling of the | |||
| watercolors and includes a paper-colored background, and | |||
| `pomological_theme_nobg()` is the same as the first, just with a | |||
| transparent (or white) background. | |||
| There are three theme-generating functions: | |||
| - `theme_pomological()` sets the plot theme to be representative of | |||
| the paper and styling of the watercolors and includes a | |||
| paper-colored background, | |||
| - `theme_pomological_nobg()` has the same styling, just with a | |||
| transparent (or white) background, | |||
| - `theme_pomological_plain()` has a white background and doesn’t | |||
| change the font unless requested. | |||
| A handwriting font is needed for the fully authentic pomological look, | |||
| and I found a few from Google Fonts that fit the bill. | |||
| - [Mr. De Haviland](https://fonts.google.com/specimen/Mr+De+Haviland) | |||
| - [Homemade Apple](https://fonts.google.com/specimen/Homemade+Apple/) | |||
| - [Amatic SC](https://fonts.google.com/specimen/Amatic+SC/) | |||
| - [Marck Script](https://fonts.google.com/specimen/Marck+Script/) | |||
| - [Mr. Bedfort](https://fonts.google.com/specimen/Mr+Bedfort/) | |||
| Alternatively, use something like | |||
| [calligrapher.com](https://www.calligraphr.com/) to create your own | |||
| handwriting font\! | |||
| ``` r | |||
| pomological_theme <- function( | |||
| base_family = 'Homemade Apple', | |||
| base_size = 16, | |||
| text.color = NULL, | |||
| plot.background.color = NULL, | |||
| panel.grid.color = NULL, | |||
| panel.grid.linetype = 'dashed', | |||
| axis.text.color = NULL, | |||
| axis.text.size = base_size * 14/16, | |||
| base_theme = ggplot2::theme_minimal() | |||
| ) { | |||
| pomological_base <- list( | |||
| "paper" = "#fffeea", | |||
| 'paper_alt' = "#f8eed1", | |||
| 'light_line' = '#efe1c6', | |||
| 'medium_line' = "#a89985", | |||
| 'darker_line' = "#6b452b", | |||
| 'black' = "#3a3e3f", | |||
| "dark_blue" = "#2b323f" | |||
| ) | |||
| base_theme + | |||
| ggplot2::theme( | |||
| text = element_text( | |||
| family = base_family, | |||
| size = base_size, | |||
| colour = ifelse(hasArg(text.color), text.color, pomological_base$dark_blue) | |||
| ), | |||
| plot.background = element_rect( | |||
| fill = ifelse(hasArg(plot.background.color), plot.background.color, pomological_base$paper), | |||
| colour = NA | |||
| ), | |||
| panel.grid = element_line( | |||
| colour = ifelse(hasArg(panel.grid.color), panel.grid.color, pomological_base$light_line), | |||
| linetype = panel.grid.linetype), | |||
| panel.grid.major = element_line( | |||
| colour = ifelse(hasArg(panel.grid.color), panel.grid.color, pomological_base$light_line), | |||
| linetype = panel.grid.linetype), | |||
| panel.grid.minor = element_blank(), | |||
| axis.text = element_text( | |||
| colour = ifelse(hasArg(axis.text.color), axis.text.color, pomological_base$medium_line), | |||
| size = axis.text.size) | |||
| ) | |||
| } | |||
| pomological_theme_nobg <- function(...) { | |||
| dots <- list(...) | |||
| dots$plot.background.color <- 'transparent' | |||
| do.call('pomological_theme', args = dots) | |||
| } | |||
| ``` | |||
| Here are the color scales you’ll need: `scale_color_pomological` and | |||
| `scale_fill_pomological`. | |||
| ``` r | |||
| # learned this from https://github.com/hrbrmstr/hrbrthemes/blob/13f9b59579f007b8a5cbe5c699cbe3ec5fdd28a1/R/color.r | |||
| pomological_pal <- function() scales::manual_pal(pomological_palette) | |||
| # Scale color | |||
| scale_colour_pomological <- function(...) ggplot2::discrete_scale("colour", "pomological", pomological_pal(), ...) | |||
| scale_color_pomological <- scale_colour_pomological | |||
| # Scale fill | |||
| scale_fill_pomological <- function(...) ggplot2::discrete_scale('fill', 'pomological', pomological_pal(), ...) | |||
| ``` | |||
| For color and fill scales, **ggpomological** provides | |||
| `scale_color_pomological()` and `scale_fill_pomological()`. | |||
| In the future, I might come back to this to | |||
| In the future, I might revisit this package to | |||
| 1. Increase colors in discrete scale | |||
| 2. Setup a color-pairs plot. Lots of great color pairs in the extracted | |||
| colors. | |||
| 2. Setup paired color scales. Lots of great color pairs in the | |||
| extracted colors. | |||
| 3. Set up continuous scale colors (we’ll see…) | |||
| ## Add paper background\! | |||
| Great, but I want my plots to look even more pomological, you say? | |||
| Perfect\! This function uses the | |||
| **ggpomological** also provides a function named `paint_pomological` | |||
| that uses the | |||
| [`magick`](https://cran.r-project.org/web/packages/magick/index.html) | |||
| package to add a pomological watercolor paper background and a subtle | |||
| texture overlay. | |||
| ``` r | |||
| paint_pomological <- function( | |||
| pomo_gg, | |||
| width = 800, | |||
| height = 500, | |||
| pointsize = 16, | |||
| pomological_background = 'pomological_bg.png', | |||
| pomological_overlay = "pomological_overlay.jpg", | |||
| outfile = NULL, | |||
| ... | |||
| ) { | |||
| requireNamespace('magick', quietly = TRUE) | |||
| requireNamespace('glue', quietly = TRUE) | |||
| if (!file.exists(pomological_background)) { | |||
| warning(glue::glue("Cannot find file \"{pomological_background}\", so you can have your plot back!")) | |||
| return(pomo_gg) | |||
| } | |||
| # Paint figure | |||
| gg_fig <- magick::image_graph(width, height, bg = 'transparent', pointsize = pointsize, ...) | |||
| print(pomo_gg) | |||
| dev.off() | |||
| if (!is.null(pomological_overlay) && file.exists(pomological_overlay)) { | |||
| pomo_over <- magick::image_read(pomological_overlay) | |||
| pomo_over <- magick::image_resize(pomo_over, glue::glue("{width}x{height}!")) | |||
| gg_fig <- magick::image_composite(gg_fig, pomo_over, "blend", compose_args = "15") | |||
| } | |||
| # Paint background | |||
| pomo_bg <- magick::image_read(pomological_background) | |||
| pomo_bg <- magick::image_resize(pomo_bg, glue::glue("{width}x{height}!")) | |||
| pomo_bg <- magick::image_crop(pomo_bg, glue::glue("{width}x{height}")) | |||
| # Paint figure onto background | |||
| pomo_img <- magick::image_composite(pomo_bg, gg_fig) | |||
| if (!is.null(outfile)) { | |||
| # Do you want your picture framed? | |||
| magick::image_write(pomo_img, outfile) | |||
| } | |||
| pomo_img | |||
| } | |||
| ``` | |||
| ## Demo\! | |||
| We’ll need dplyr and ggplot2 | |||
| We’ll need ggplot2 (loaded with **ggpomological**) and dplyr | |||
| ``` r | |||
| library(ggpomological) | |||
| library(dplyr) | |||
| ``` | |||
| ## | |||
| ## Attaching package: 'dplyr' | |||
| ## The following objects are masked from 'package:stats': | |||
| ## | |||
| ## filter, lag | |||
| ## The following objects are masked from 'package:base': | |||
| ## | |||
| ## intersect, setdiff, setequal, union | |||
| ``` r | |||
| library(ggplot2) | |||
| ``` | |||
| ### Basic iris plot | |||
| @@ -285,24 +123,35 @@ basic_iris_plot | |||
| <!-- --> | |||
| ``` r | |||
| # With pomological theme | |||
| basic_iris_plot + | |||
| pomological_theme() + | |||
| scale_color_pomological() | |||
| # With pomological colors | |||
| basic_iris_plot <- basic_iris_plot + scale_color_pomological() | |||
| basic_iris_plot | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| # With transparent background | |||
| pomological_iris <- basic_iris_plot + | |||
| pomological_theme_nobg() + | |||
| scale_color_pomological() | |||
| pomological_iris | |||
| # With pomological theme | |||
| pomological_iris <- basic_iris_plot + theme_pomological() | |||
| pomological_iris | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| # With transparent background | |||
| basic_iris_plot + theme_pomological_nobg() | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| # Or with "plain" pomological | |||
| basic_iris_plot + theme_pomological_plain() | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| # Painted! | |||
| paint_pomological(pomological_iris, res = 110) %>% | |||
| @@ -319,17 +168,18 @@ stacked_bar_plot <- ggplot(diamonds) + | |||
| geom_histogram(binwidth = 850) + | |||
| xlab('Price (USD)') + | |||
| ylab('Count') + | |||
| ggtitle("ggpomological") + | |||
| scale_x_continuous(label = scales::dollar_format()) + | |||
| scale_fill_pomological() | |||
| stacked_bar_plot + pomological_theme() | |||
| stacked_bar_plot + theme_pomological() | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| paint_pomological( | |||
| stacked_bar_plot + pomological_theme_nobg(), | |||
| stacked_bar_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-bar-chart-painted.png") | |||
| @@ -349,14 +199,14 @@ density_plot <- mtcars %>% | |||
| scale_color_pomological() + | |||
| scale_fill_pomological() | |||
| density_plot + pomological_theme() | |||
| density_plot + theme_pomological() | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| paint_pomological( | |||
| density_plot + pomological_theme_nobg(), | |||
| density_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-density-demo-painted.png") | |||
| @@ -373,7 +223,7 @@ big_volume_cities <- txhousing %>% | |||
| group_by(city) %>% | |||
| summarize(mean_volume = mean(volume, na.rm = TRUE)) %>% | |||
| arrange(-mean_volume) %>% | |||
| top_n(length(pomological_palette)) %>% | |||
| top_n(length(ggpomological:::pomological_palette)) %>% | |||
| pull(city) | |||
| ``` | |||
| @@ -393,14 +243,14 @@ full_bar_stack_plot <- txhousing %>% | |||
| theme(panel.grid.minor.x = element_blank()) + | |||
| scale_fill_pomological() | |||
| full_bar_stack_plot + pomological_theme() | |||
| full_bar_stack_plot + theme_pomological() | |||
| ``` | |||
| <!-- --> | |||
| ``` r | |||
| paint_pomological( | |||
| full_bar_stack_plot + pomological_theme_nobg(), | |||
| full_bar_stack_plot + theme_pomological_nobg(), | |||
| res = 110 | |||
| ) %>% | |||
| magick::image_write("Readme_files/figure-gfm/plot-full-bar-stack-painted.png") | |||
| @@ -410,13 +260,13 @@ paint_pomological( | |||
| ### One last plot | |||
| (in my handwriting) | |||
| Using my own handwriting and the `ggridges` package. | |||
| ``` r | |||
| ridges_pomological <- ggplot(diamonds) + | |||
| aes(x = carat, y = clarity, color = clarity, fill = clarity) + | |||
| ggridges::geom_density_ridges(alpha = 0.75) + | |||
| pomological_theme_nobg( | |||
| theme_pomological_nobg( | |||
| base_family = 'gWriting', | |||
| base_size = 20, | |||
| base_theme = ggridges::theme_ridges() | |||
| @@ -431,100 +281,3 @@ paint_pomological(ridges_pomological, res = 110) %>% | |||
| ## Picking joint bandwidth of 0.057 | |||
|  | |||
| ## Appendix | |||
| <details> | |||
| <summary>Some functions I wrote while exploring colors, that may or may | |||
| not work here.</summary> | |||
| ``` r | |||
| # load all colors | |||
| x <- readLines("pomological.css") | |||
| x <- stringr::str_extract(x, "#[0-9a-f]{6}") | |||
| x <- x[!is.na(x)] | |||
| gg_color_hue <- function(n) { | |||
| hues = seq(15, 375, length = n + 1) | |||
| hcl(h = hues, l = 65, c = 100)[1:n] | |||
| } | |||
| col2hsv <- function(x) rgb2hsv(col2rgb(x)) | |||
| dist2ref_color <- function(color, ref_color) { | |||
| stopifnot(length(ref_color) == 1) | |||
| x <- col2hsv(c(color, ref_color)) %>% | |||
| t %>% | |||
| dist %>% | |||
| as.matrix %>% | |||
| {tibble('ref_color' = .[length(color) + 1, 1:length(color)])} | |||
| names(x) <- ref_color | |||
| x | |||
| } | |||
| compare_to_ggplot <- function(compare_to_ggplot) { | |||
| pomo_gg <- map_dfr(set_names(compare_to_ggplot), ~ as_tibble(t(col2hsv(.))), .id = "color") %>% | |||
| bind_cols( | |||
| map_dfc(gg_color_hue(set_names(length(compare_to_ggplot))), ~ dist2ref_color(compare_to_ggplot, .)) | |||
| ) %>% | |||
| tidyr::gather('ggplot_color', 'dist', -color:-v) %>% | |||
| # group_by(color) %>% | |||
| # do(dist = min(.$dist), ggplot_color = filter(., dist == min(.$dist))$ggplot_color) %>% | |||
| # mutate(dist = map_dbl(dist, ~ .), ggplot_color = map_chr(ggplot_color, ~ .)) %>% | |||
| # ungroup %>% | |||
| mutate(ggplot_color = factor(ggplot_color, gg_color_hue(length(compare_to_ggplot)))) %>% | |||
| arrange(ggplot_color) | |||
| warning(glue::glue("Palette has {length(compare_to_ggplot)} colors"), call. = FALSE) | |||
| ggplot(pomo_gg) + | |||
| aes(x = ggplot_color, y = dist, fill = color, label = color) + | |||
| geom_label(color = 'white')+ | |||
| # geom_point(shape = 15, size = 5) + | |||
| scale_fill_identity() | |||
| } | |||
| data_frame( | |||
| 'color' = color_options, | |||
| # 'group' = sample(c('pomo', 'logical'), length(color_options), replace = TRUE), | |||
| 'x' = pmap_chr(tidyr::crossing(letters, letters), ~paste0(..1, ..2))[1:length(color_options)], | |||
| 'y' = 1:length(color_options) | |||
| ) %>% | |||
| ggplot() + | |||
| aes(x, y, fill = color) + | |||
| # geom_point(size = 8)+ | |||
| geom_col()+ | |||
| geom_text(aes(label = color), hjust = -0.1) + | |||
| scale_fill_identity() + | |||
| coord_flip() + | |||
| theme_minimal() + | |||
| #theme_xkcd() + | |||
| theme( | |||
| text = element_text(family = 'gWriting', size = 16), | |||
| plot.background = element_rect(fill = base_colors["paper_light"], color = NA), | |||
| panel.grid = element_line(color = "#efe1c6"), | |||
| axis.text = element_text(color = "#655843", size = 14) | |||
| ) | |||
| ordered_plot <- function(color_options, dichromat = FALSE) { | |||
| if (dichromat) { | |||
| dichr_type <- sample(c("deutan", "protan", "tritan"), 1) | |||
| message(glue::glue("color blindness: {dichr_type}")) | |||
| color_options <- dichromat::dichromat(color_options, dichr_type) | |||
| } | |||
| data_frame( | |||
| color = color_options, | |||
| x = 1, | |||
| y = 1:length(color_options) | |||
| ) %>% | |||
| ggplot() + | |||
| aes(x, y, fill = color, label = color) + | |||
| geom_tile() + | |||
| geom_label(color = 'white') + | |||
| scale_fill_identity()+ | |||
| scale_y_continuous(breaks = 1:length(color_options), labels = 1:length(color_options))+ | |||
| theme_minimal() | |||
| } | |||
| ``` | |||
| </details> | |||
| @@ -0,0 +1,26 @@ | |||
| % Generated by roxygen2: do not edit by hand | |||
| % Please edit documentation in R/ggpomological-package.R | |||
| \docType{package} | |||
| \name{ggpomological-package} | |||
| \alias{ggpomological} | |||
| \alias{ggpomological-package} | |||
| \title{A Pomological ggplot2 Theme} | |||
| \description{ | |||
| This package provides a ggplot2 theme inspired by the | |||
| \href{https://usdawatercolors.nal.usda.gov/pom}{USDA Pomological Watercolors collection} | |||
| and by Aron Atkins's (\href{https://twitter.com/aronatkins]}{@aronatkins}) | |||
| \href{https://github.com/rstudio/rstudio-conf/tree/master/2018/Fruit_For_Thought--Aron_Atkins}{talk on parameterized RMarkdown} | |||
| at \href{https://www.rstudio.com/conference/}{rstudio::conf 2018}. | |||
| } | |||
| \seealso{ | |||
| Useful links: | |||
| \itemize{ | |||
| \item \url{https://github.com/gadenbuie/ggpomological} | |||
| \item Report bugs at \url{https://github.com/gadenbuie/ggpomological/issues} | |||
| } | |||
| } | |||
| \author{ | |||
| \strong{Maintainer}: Garrick Aden-Buie \email{g.adenbuie@gmail.com} | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| % Generated by roxygen2: do not edit by hand | |||
| % Please edit documentation in R/paint_pomological.R | |||
| \name{paint_pomological} | |||
| \alias{paint_pomological} | |||
| \title{Paint a ggpomological watercolor} | |||
| \usage{ | |||
| paint_pomological(pomo_gg, width = 800, height = 500, pointsize = 16, | |||
| outfile = NULL, pomological_background = pomological_images("background"), | |||
| pomological_overlay = pomological_images("overlay"), ...) | |||
| } | |||
| \arguments{ | |||
| \item{pomo_gg}{A pomologically styled ggplot2 object. See \code{\link[=theme_pomological]{theme_pomological()}}} | |||
| \item{width}{Width of output image in pixels} | |||
| \item{height}{Height of output image in pixels} | |||
| \item{pointsize}{Text size for plot text} | |||
| \item{outfile}{Optional name for output file if you'd like to save the image} | |||
| \item{pomological_background}{Paper image, defaults to paper texture provided | |||
| by ggpomological.} | |||
| \item{pomological_overlay}{Overlay texture. Set to \code{NULL} for no texture.} | |||
| \item{...}{Arguments passed on to \code{magick::image_graph} | |||
| \describe{ | |||
| \item{res}{resolution in pixels} | |||
| \item{clip}{enable clipping in the device. Because clipping can slow things down | |||
| a lot, you can disable it if you don't need it.} | |||
| \item{antialias}{TRUE/FALSE: enables anti-aliasing for text and strokes} | |||
| }} | |||
| } | |||
| \description{ | |||
| Uses \link{magick} to paint a pomological watercolor. (Paints your plot onto a | |||
| pomological watercolor style paper, with texture overlay.) | |||
| } | |||
| \references{ | |||
| https://usdawatercolors.nal.usda.gov/pom | |||
| } | |||
| \seealso{ | |||
| \link{theme_pomological} | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| % Generated by roxygen2: do not edit by hand | |||
| % Please edit documentation in R/scale_pomological.R | |||
| \name{scale_pomological} | |||
| \alias{scale_pomological} | |||
| \alias{scale_colour_pomological} | |||
| \alias{scale_color_pomological} | |||
| \alias{scale_fill_pomological} | |||
| \title{Pomological Color and Fill Scales} | |||
| \usage{ | |||
| scale_colour_pomological(...) | |||
| scale_color_pomological(...) | |||
| scale_fill_pomological(...) | |||
| } | |||
| \arguments{ | |||
| \item{...}{Arguments passed on to \code{ggplot2::discrete_scale} | |||
| \describe{ | |||
| \item{aesthetics}{The names of the aesthetics that this scale works with} | |||
| \item{scale_name}{The name of the scale} | |||
| \item{palette}{A palette function that when called with a single integer | |||
| argument (the number of levels in the scale) returns the values that | |||
| they should take} | |||
| \item{name}{The name of the scale. Used as axis or legend title. If | |||
| \code{waiver()}, the default, the name of the scale is taken from the first | |||
| mapping used for that aesthetic. If \code{NULL}, the legend title will be | |||
| omitted.} | |||
| \item{breaks}{One of: | |||
| \itemize{ | |||
| \item \code{NULL} for no breaks | |||
| \item \code{waiver()} for the default breaks computed by the | |||
| transformation object | |||
| \item A character vector of breaks | |||
| \item A function that takes the limits as input and returns breaks | |||
| as output | |||
| }} | |||
| \item{labels}{One of: | |||
| \itemize{ | |||
| \item \code{NULL} for no labels | |||
| \item \code{waiver()} for the default labels computed by the | |||
| transformation object | |||
| \item A character vector giving labels (must be same length as \code{breaks}) | |||
| \item A function that takes the breaks as input and returns labels | |||
| as output | |||
| }} | |||
| \item{limits}{A character vector that defines possible values of the scale | |||
| and their order.} | |||
| \item{expand}{Vector of range expansion constants used to add some | |||
| padding around the data, to ensure that they are placed some distance | |||
| away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} | |||
| to generate the values for the \code{expand} argument. The defaults are to | |||
| expand the scale by 5\% on each side for continuous variables, and by | |||
| 0.6 units on each side for discrete variables.} | |||
| \item{na.translate}{Unlike continuous scales, discrete scales can easily show | |||
| missing values, and do so by default. If you want to remove missing values | |||
| from a discrete scale, specify \code{na.translate = FALSE}.} | |||
| \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic | |||
| value should missing be displayed as? Does not apply to position scales | |||
| where \code{NA} is always placed at the far right.} | |||
| \item{drop}{Should unused factor levels be omitted from the scale? | |||
| The default, \code{TRUE}, uses the levels that appear in the data; | |||
| \code{FALSE} uses all the levels in the factor.} | |||
| \item{guide}{A function used to create a guide or its name. See | |||
| \code{\link[=guides]{guides()}} for more info.} | |||
| \item{position}{The position of the axis. "left" or "right" for vertical | |||
| scales, "top" or "bottom" for horizontal scales} | |||
| \item{super}{The super class to use for the constructed scale} | |||
| }} | |||
| } | |||
| \description{ | |||
| Color scales based on the USDA Pomological Watercolors paintings. | |||
| } | |||
| \references{ | |||
| https://usdawatercolors.nal.usda.gov/pom | |||
| } | |||
| \seealso{ | |||
| \link[ggplot2:scale_colour_discrete]{ggplot2::scale_colour_discrete} \link[ggplot2:scale_fill_discrete]{ggplot2::scale_fill_discrete} | |||
| } | |||
| @@ -0,0 +1,109 @@ | |||
| % Generated by roxygen2: do not edit by hand | |||
| % Please edit documentation in R/theme_pomological.R | |||
| \name{theme_pomological} | |||
| \alias{theme_pomological} | |||
| \alias{theme_pomological_nobg} | |||
| \alias{theme_pomological_plain} | |||
| \title{Pomological Theme} | |||
| \usage{ | |||
| theme_pomological(base_family = "Homemade Apple", base_size = 18, | |||
| text.color = pomological_base$dark_blue, | |||
| plot.background.color = pomological_base$paper, | |||
| panel.border.color = pomological_base$light_line, with.panel.grid = FALSE, | |||
| panel.grid.color = pomological_base$light_line, | |||
| panel.grid.linetype = "dashed", | |||
| axis.text.color = pomological_base$medium_line, axis.text.size = base_size | |||
| * 3/4, base_theme = ggplot2::theme_minimal()) | |||
| theme_pomological_nobg(...) | |||
| theme_pomological_plain(...) | |||
| } | |||
| \arguments{ | |||
| \item{base_family}{Base text family. See \strong{Fonts} in \code{\link[=theme_pomological]{theme_pomological()}} | |||
| for some examples from Google Fonts options, including \code{"Mr De Haviland"}, | |||
| \code{"Homemade Apple"}, \code{"Marck Script"}, and \code{"Mr. Bedfort"}. For the | |||
| authentic pomological look, use \code{"Homemade Apple"} or \code{"Mr De Haviland"}. | |||
| Set to \code{NULL} or use \code{\link[=theme_pomological_plain]{theme_pomological_plain()}} for no change to fonts.} | |||
| \item{base_size}{Base text size} | |||
| \item{text.color}{Color of all text (except axis text, see \code{axis.text.color})} | |||
| \item{plot.background.color}{Color of plot background, passed to \code{plot.background}} | |||
| \item{panel.border.color}{Color of plot panel border} | |||
| \item{with.panel.grid}{If \code{FALSE} gridlines in plot are removed} | |||
| \item{panel.grid.color, panel.grid.linetype}{Color and linetype of panel grid, passed to \code{panel.grid}} | |||
| \item{axis.text.color, axis.text.size}{Color and size of axis text} | |||
| \item{base_theme}{Starting theme of plot, default is | |||
| \code{\link[ggplot2:theme_minimal]{ggplot2::theme_minimal()}}. Any elements set by \code{theme_pomological()} will | |||
| overwrite the \code{base_theme} unless the specific parameter is explicitly set | |||
| to \code{NULL}.} | |||
| } | |||
| \description{ | |||
| \link{ggplot2} plot theme based on the USDA Pomological Watercolors paintings. | |||
| } | |||
| \section{Functions}{ | |||
| \itemize{ | |||
| \item \code{theme_pomological_nobg}: Pomological theme with white (transparent) background | |||
| \item \code{theme_pomological_plain}: A "plain" pomological theme with white | |||
| background and normal fonts. | |||
| }} | |||
| \section{Fonts}{ | |||
| Complete the pomological watercolor theme with a handwriting or cursive font. | |||
| The following fonts from \href{https://fonts.google.com}{Google Fonts} work well. | |||
| Visit the links below to install on your system. | |||
| \itemize{ | |||
| \item \href{https://fonts.google.com/specimen/Homemade+Apple/}{Homemade Apple} | |||
| \item \href{https://fonts.google.com/specimen/Mr+De+Haviland}{Mr. De Haviland} | |||
| \item \href{https://fonts.google.com/specimen/Marck+Script/}{Marck Script} | |||
| \item \href{https://fonts.google.com/specimen/Mr+Bedfort/}{Mr. Bedfort} | |||
| } | |||
| Fonts with R are notoriously tricky, so these may not work well for you. If | |||
| you have installed the fonts but they aren't showing up or working, you can | |||
| always try running \code{extrafont::font_import()} or \code{extrafont::load_fonts()} in | |||
| the session or RMarkdown document. Or you can use \code{\link[=theme_pomological_plain]{theme_pomological_plain()}}. | |||
| } | |||
| \examples{ | |||
| library(ggplot2) | |||
| basic_iris_plot <- ggplot(iris) + | |||
| aes(x = Sepal.Length, y = Sepal.Width, color = Species) + | |||
| geom_point(size = 2) + | |||
| # with pomological color scale | |||
| scale_color_pomological() | |||
| # Pomological Theme | |||
| basic_iris_plot + | |||
| theme_pomological() | |||
| # Don't change panel grid color | |||
| basic_iris_plot + | |||
| theme_pomological( | |||
| panel.grid.color = NULL | |||
| ) | |||
| # White background | |||
| basic_iris_plot + | |||
| theme_pomological_nobg() | |||
| # Plain plot without font or background | |||
| basic_iris_plot + | |||
| theme_pomological_plain() | |||
| } | |||
| \references{ | |||
| https://usdawatercolors.nal.usda.gov/pom | |||
| } | |||
| \seealso{ | |||
| \link[ggplot2:theme]{ggplot2::theme} | |||
| } | |||