3

I have a theme function and I would like to add scale_fill_manual(values=x) inside the function and update all of my plots but it does not work if I add this line inside my_theme function. Also I don't know how to supress the messages from loading the library using reprex.

library(tidyverse, quietly = TRUE)

# Here I just create my HEX colors from RGB colors.  
x <-   tibble(r = c(187, 6, 226, 78, 221),
              g = c(180, 110, 223, 118, 128),
              b = c(135, 159, 204, 109, 71))


x <- modify(x, as.hexmode) %>%
  unite(r, g, b, col="hex", sep="") %>%
  map_df(~paste0("#", .x)) %>%
  pull()

# This is my theme function and I would like to add scale_fill_manual, 
# but then it does not work. I have tried different combinations.
my_theme <- function(){
    theme_minimal() +
    theme(title = element_text(color = "gray25"),
          plot.subtitle = element_text(size=12),
          plot.title = element_text(size=12),
          plot.caption = element_text(color= "gray30")) 

}

# But if I just add it in a separate line then it works. 
mpg %>% 
  ggplot() +
  geom_bar(aes(x = fct_infreq(class), fill=factor(cyl)), color="black", width = 0.5) +
  labs(title= "CK farver") +
  my_theme() +
  scale_fill_manual(values = x) +
  theme(axis.text.x = element_text(angle = -90, hjust = 0)) 

Created on 2019-04-16 by the reprex package (v0.2.0).

Z.Lin
  • 28,055
  • 6
  • 54
  • 94
xhr489
  • 1,957
  • 13
  • 39

1 Answers1

3

Unless you intend to pass additional theme specifications into my_theme, I don't think there's really a need to define it as a function. A list would do fine.

The following should work for your purpose:

my_theme2 <- list(
  theme_minimal() +
    theme(title = element_text(color = "gray25"),
          plot.subtitle = element_text(size=12),
          plot.title = element_text(size=12),
          plot.caption = element_text(color= "gray30")) ,
  scale_fill_manual(values = x)
)

mpg %>% 
  ggplot() +
  geom_bar(aes(x = fct_infreq(class), fill=factor(cyl)), color="black", width = 0.5) +
  labs(title= "CK farver") +
  my_theme2 + 
  theme(axis.text.x = element_text(angle = -90, hjust = 0))

(Output plot not shown, because it's identical to the one in the question)

edit with function version of the above:

my_theme3 <- function(...){
  list(
    theme_minimal() +
      theme(title = element_text(color = "gray25"),
            plot.subtitle = element_text(size=12),
            plot.title = element_text(size=12),
            plot.caption = element_text(color= "gray30"),
            ...) ,
    scale_fill_manual(values = x)
  )
}

# same plot as before
mpg %>% 
  ggplot() +
  geom_bar(aes(x = fct_infreq(class), fill=factor(cyl)), color="black", width = 0.5) +
  labs(title= "CK farver") +
  my_theme3() +
  theme(axis.text.x = element_text(angle = -90, hjust = 0))

# if you want to add other tweaks to the theme, e.g. red labels, different legend position
mpg %>% 
  ggplot() +
  geom_bar(aes(x = fct_infreq(class), fill=factor(cyl)), color="black", width = 0.5) +
  labs(title= "CK farver") +
  my_theme3(axis.text = element_text(color = "red"),
            legend.position = "bottom") +
  theme(axis.text.x = element_text(angle = -90, hjust = 0))
Z.Lin
  • 28,055
  • 6
  • 54
  • 94
  • thanks well it works, but how come you put ``scale_fill_manual`` inside ``theme`` and not as a line for itself separated by a ``+``?? – xhr489 Apr 16 '19 at 10:01
  • @David `scale_*` is a separate component of the list here. Multiple components can be added to a ggplot object in one swop if they are in a list. You can see this in the last example in `?%+%`. & if you want to see the underlying code, the relevant method is defined [here](https://github.com/tidyverse/ggplot2/blob/868fdb7c9176be685850a3a698af7acb5e890a4a/R/plot-construction.r), in `ggplot2:::ggplot_add.list`. – Z.Lin Apr 16 '19 at 10:10
  • @ Z.Lin: great thanks, but what if I want to keep my function? Can you please also provide the solution in function form? – xhr489 Apr 16 '19 at 10:15
  • @David Sure. Edited. – Z.Lin Apr 16 '19 at 10:19