I want my ggplots to looke like the color palette I’ve chosen as my own (big shoutout to Paletton for helping me with this). I’m going to use the ggthemr package to do this.

devtools::install_github("cttobin/ggthemr")
library(ggthemr)

?ggthemr::define_palette
?ggthemr_palette
?ggthemr

OK I think I’m getting this. My colors are as follows:

mypal <- read.csv("data/palette_lighter.csv", 
                  stringsAsFactors = FALSE)

difs <- cumsum(rep(c(120, 150, 150), 4))
angs <- (210 + c(0, difs)) %% 360
angs <- unique(angs)
# angs <- seq(from = 210, by = 120, length.out = 13) %% 360
ords <- match(angs, mypal$angle)

myswatch <- c("#7d7d7d", mypal$darkest[ords])
barplot(rep(1, length(myswatch)), col = myswatch)
barplot(rep(1, 2), col = mypal$darkest[c(1, 3)])

ggpal1 <- ggthemr_palette(swatch = myswatch,
                          gradient = mypal$darkest[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#ffffff",
                          line = c("#6e6e6e", "#6e6e6e"), gridline = "#c3c3c3")
?ggthemr
mytheme <- ggthemr(ggpal1, set_theme = FALSE)
# ggthemr(ggpal1)

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  mytheme$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme$scales$scale_colour_discrete()

ggplot(diamonds, aes(x=carat, y=price, color=as.numeric(as.factor(clarity)))) + 
  geom_point() +
  mytheme$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme$scales$scale_colour_gradient()

Actually I think I need to be more deliberate about choosing a color scale (swatch).

I’m going to try using the colorspace package to do this.

I want my workflow to be:

  1. Choose a color, possibly as a 6-digit hex.
  2. Convert to hsl/hsv
  3. Select colors from different angles (hues) of the current saturation and lightness.
library(colorspace)

myrgb <- colorspace::hex2RGB(mypal$darkest[1])
mylch <- as(myrgb, "polarLUV")
mylch

Unfortunately, there doesn’t seem to be a good way to go from hex to hsv/hsl in R. Instead, I can go from hex to LCH, which according to Wikipedia is similar, but uses Chroma (“relative saturation”) instead of Saturation. I’m fine with this, but I do begrudge the difference in acronym ordering. What does it look like when I take different H values with the same L and C?

class(mylch)
?polarLUV
  • A different SO thread pointsout that it might be best to use colors that are closer together in color space.
  • A nice applet implements this idea, specially geared toward data scientists.

I’m going to try just using my original palette and selecting different shades, including gray, to get enough.

myswatch2 <- c(mypal$darkest[1:4], "#7d7d7d", mypal$lighter[1:4])
barplot(rep(1, length(myswatch2)), col = myswatch2)
barplot(rep(1, 2), col = mypal$darkest[c(1, 3)])

ggpal2 <- ggthemr_palette(swatch = myswatch2,
                          gradient = mypal$darkest[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#dddddd",
                          line = c("#6e6e6e", "#6e6e6e"), gridline = "#c3c3c3")

How’s it look?

mytheme2 <- ggthemr(ggpal2, set_theme = FALSE)
# ggthemr(ggpal1)

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  mytheme2$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme2$scales$scale_colour_discrete()

Let’s try a darker one.

myswatch3 <- c(mypal$lightest[1:4], "#000000", mypal$mid[1:4])
barplot(rep(1, length(myswatch3)), col = myswatch3)
barplot(rep(1, 2), col = mypal$lightest[c(1, 3)])

ggpal3 <- ggthemr_palette(swatch = myswatch3,
                          gradient = mypal$darkest[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#555555",
                          line = c("#6e6e6e", "#6e6e6e"), gridline = "#c3c3c3")
mytheme3 <- ggthemr(ggpal3, set_theme = FALSE)
# ggthemr(ggpal1)

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  mytheme3$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme3$scales$scale_colour_discrete()

I’m not crazy about the light on dark. I think it needs to be darker on dark. I’m going to play around and see what comes out.

But for now I need to see why the background only applies to the plot. … OK, I need to set type="outer" for this to happen.

myswatch3 <- c(mypal$lightest[1:4], "#000000", mypal$mid[1:4])
barplot(rep(1, length(myswatch3)), col = myswatch3)
barplot(rep(1, 2), col = mypal$lightest[c(1, 3)])

ggpal3 <- ggthemr_palette(swatch = myswatch3,
                          gradient = mypal$darkest[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#555555",
                          line = c("#6e6e6e", "#6e6e6e"), 
                          gridline = "#c3c3c3", text = "#c3c3c3")
mytheme3 <- ggthemr(ggpal3, set_theme = FALSE, type = "outer")
# ggthemr(ggpal1)

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  mytheme3$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme3$scales$scale_colour_discrete()

That’s fine for now.

The next thing that’s missing is font. I had tried to mess with this before, and what I remember is:

  • It’s fairly easy to change in raster (png, etc.) devices with ggplot.
  • It’s absurdly difficult to change with the postscript device.

Here goes!

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  mytheme3$theme +
  # mytheme$scales$scale_colour_discrete()
  mytheme3$scales$scale_colour_discrete() +
  ggtitle("This is the plot title. Lorem ipsum et cetera") +
  theme(text = element_text(family = "Cutive Mono", face = "plain"), 
        axis.title = element_text(family = "Domine", face = "plain"),
        plot.title=element_text(family = "Domine", face = "bold", size = 20))

Cool! Next I want to play around with a different package, colourlovers, which provides access to the COLOURlovers API.

devtools::install_github("leeper/colourlovers")

library(colourlovers)

This makes picking colors a lot more fun, since it just requires picking a palette you like from the colourlovers website.

I’m going with one from Adventure Time.

Quick aside, since I decided to pick an Adventure Time font too: I need to remember to do the following when importing a new (truetype) font:

  1. Get the ttf file
  2. Register it with the system, using gnome-font-viewer (should be default application)
  3. Run extrafont::font_import([fontpath]). Important to specify [fontpath] so that this doesn’t try to re-import all fonts and take forever
atswatch <- swatch(clpalette(id = 2539607))[[1]]
pbswatch <- swatch(clpalette(id = 1925758))[[1]]
#   c(mypal$lightest[1:4], "#000000", mypal$mid[1:4])
# barplot(rep(1, length(myswatch3)), col = myswatch3)
# barplot(rep(1, 2), col = mypal$lightest[c(1, 3)])

atpal <- ggthemr_palette(swatch = c(atswatch[-2], pbswatch),
                          gradient = atswatch[c(1, 2)],
                          # background = mypal$lightest[1],
                          background = atswatch[2],
                          line = c("#6e6e6e", "#6e6e6e"), 
                          gridline = "#c3c3c3", text = "#444444")
attheme <- ggthemr(atpal, set_theme = FALSE, type = "outer")
# ggthemr(ggpal1)


ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  attheme$theme +
  attheme$scales$scale_colour_discrete() +
  ggtitle("This is the plot title. Lorem ipsum et cetera") +
  theme(text = element_text(family = "ShortStack"), 
        plot.title=element_text(family = "PiecesOfEight", face = "plain", size = 20))

I’m happy with where this is at. Next steps are to package it up and use what I’ve learned to personalize my own theme.

Personal theme

I think I’ll make 2 themes–one dark and one light. The light one may as well blend into my blog background color.

myswatch3 <- c(mypal$lightest[1:4], "#000000", mypal$mid[1:4])
barplot(rep(1, length(myswatch3)), col = myswatch3)
barplot(rep(1, 2), col = mypal$lightest[c(1, 3)])
darkpal1 <- ggthemr_palette(swatch = myswatch3,
                          # gradient = mypal$darkest[c(1, 3)],
                          gradient = mypal$mid[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#555555",
                          line = c("#6e6e6e", "#6e6e6e"), 
                          gridline = "#c3c3c3", text = "#c3c3c3")
darktheme1 <- ggthemr(darkpal1, set_theme = FALSE, type = "outer")

ggplot(mtcars, aes(x = disp, y = hp, col = mpg, size = mpg)) + 
  geom_point() + 
  darktheme1$theme +
  darktheme1$scales$scale_colour_gradient()


darkpal2 <- ggthemr_palette(swatch = myswatch3,
                          # gradient = mypal$darkest[c(1, 3)],
                          gradient = mypal$darkest[c(1, 3)],
                          # background = mypal$lightest[1],
                          background = "#555555",
                          line = c("#6e6e6e", "#6e6e6e"), 
                          gridline = "#c3c3c3", text = "#c3c3c3")
darktheme2 <- ggthemr(darkpal2, set_theme = FALSE, type = "outer")

ggplot(mtcars, aes(x = disp, y = hp, fill = mpg, size = mpg)) + 
  geom_point(shape = 21, color = "#c3c3c3", alpha = 0.5) + 
  darktheme2$theme +
  darktheme2$scales$scale_fill_gradient()
marktheme_dark <- darktheme2$theme +
  theme(text = element_text(family = "Cutive Mono", face = "plain"), 
        axis.title = element_text(family = "Domine", face = "plain"),
        plot.title=element_text(family = "Domine", face = "bold", size = 20))


ggplot(mtcars, aes(x = disp, y = hp, fill = mpg, size = mpg)) + 
  geom_point(shape = 21, color = "#c3c3c3", alpha = 0.5) + 
  marktheme_dark +
  darktheme2$scales$scale_fill_gradient()

I’d say that’s a damn good dark theme. Now for something lighter.

lightswatch <- c(mypal$darkest[1:4], "#555555", mypal$mid[1:4])
lightpal <- ggthemr_palette(swatch = lightswatch,
                          gradient = mypal$darkest[c(1, 3)],
                          background = mypal$lightest[1],
                          # background = "#555555",
                          line = c("#222222", "#222222"), 
                          gridline = "#c3c3c3", text = "#222222")

lighttheme <- ggthemr(lightpal, set_theme = FALSE, type = "outer")


ggplot(mtcars, aes(x = disp, y = hp, fill = mpg, size = mpg)) + 
  geom_point(shape = 21, color = "#555555", alpha = 0.75) + 
  lighttheme$theme +
  lighttheme$scales$scale_fill_gradient()

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) + 
  geom_point() +
  lighttheme$theme +
  lighttheme$scales$scale_colour_discrete() +
  ggtitle("This is the plot title. Lorem ipsum et cetera") +
  theme(text = element_text(family = "ShortStack"), 
        plot.title=element_text(family = "PiecesOfEight", face = "plain", size = 20))
marktheme_light <- lighttheme$theme +
  theme(text = element_text(family = "Cutive Mono", face = "plain"), 
        axis.title = element_text(family = "Domine", face = "plain"),
        plot.title=element_text(family = "Domine", face = "bold", size = 20))

ggplot(mtcars, aes(x = disp, y = hp, fill = mpg, size = mpg)) + 
  geom_point(shape = 21, color = "#555555", alpha = 0.75) + 
  marktheme_light +
  lighttheme$scales$scale_fill_gradient()

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) +
  geom_point() +
  marktheme_light +
  lighttheme$scales$scale_colour_discrete() +
  ggtitle("This is the plot title. Lorem ipsum et cetera")

Next I’m going to package these up. I’m going to do this in a package I keep for plotting, markplots. I’ll have to add my theme:

markpal <- mypal
devtools::use_data(markpal, pkg = "~/GoogleDrive/R/markplots/", 
                   internal = FALSE, overwrite = TRUE)

devtools::use_data(attheme, pkg = "~/GoogleDrive/R/markplots/", 
                   internal = FALSE, overwrite = TRUE)

devtools::use_data(marktheme_dark, pkg = "~/GoogleDrive/R/markplots/", 
                   internal = FALSE, overwrite = TRUE)
devtools::use_data(marktheme_light, pkg = "~/GoogleDrive/R/markplots/", 
                   internal = FALSE, overwrite = TRUE)

Now I’m going to try a different approach using functions in the colorspace package. I also want to try a new palette I created on colourlovers.

clpng(clpalette(id = 4511587))

gehex <- paste0("#", unlist(gepal$colors))
gehsv <- hex2hsv(gehex[2]) %>% 
  as.data.frame()
gepal <- read.csv("data/palette_ge.csv", stringsAsFactors = FALSE)
gepalette_dark <- ggthemr_palette(background = gehex[1], swatch = gepal$hex,
                                  gridline = gepal$hex[5],
                                  gradient = c(gepal$hex[7], gepal$hex[9]),
                                  text = c(gepal$hex[4], gepal$hex[4]),
                                  line = c(gepal$hex[5], gepal$hex[5]))

getheme_dark <- ggthemr(palette = gepalette_dark, type = "outer", set_theme = FALSE)
ermatheme_dark <- getheme_dark$theme +
  theme(text = element_text(family = "Cutive Mono", face = "plain"), 
        axis.title = element_text(family = "Domine", face = "plain"),
        plot.title=element_text(family = "Domine", face = "bold", size = 20))

ggplot(mtcars, aes(x = disp, y = hp, fill = mpg, size = mpg)) + 
  geom_point(shape = 21, color = "#555555") + 
  ermatheme_dark +
  scale_fill_continuous(guide = "legend", low = gepal$hex[9], high = gepal$hex[7])

ggplot(diamonds, aes(x=carat, y=price, color=clarity)) +
  geom_point() +
  ermatheme_dark +
  getheme_dark$scales$scale_colour_discrete() +
  ggtitle("This is the plot title. Lorem ipsum et cetera")