Lucas Spangher
Lucas Spangher

Reputation: 359

Replace one ggplot default theme element with an element from another default theme

I really like everything about ggplot2's ggtheme's theme_fivethirtyeight() except for the fact that it hides all axis titles.

How can I use theme_fivethirtyeight() but tell it to inherit the axis title specification from another theme?

Upvotes: 3

Views: 2210

Answers (3)

Christian
Christian

Reputation: 1052

ggplot_merge_styles <- function(theme, ...) {
  elements <- lapply(as.list(match.call())[-1], function(x) eval(parse(text=deparse(x))))
  for (element in names(elements)) {
    if (element != 'theme') {
      theme[[element]] <- elements[[element]]
    }
  }
  
  return(theme)
}

Then you can specify certain design attributes and merge them together with other styles.

For instance, I enjoy the theme_minimal()'s design on plot.title, except that I want it to be coloured gray instead of it's ordinary black. Then by running the following code, all plot.title properties are preserved except for colour which is being replaced:

plot <- 
  ... +
  theme(plot.title = ggplot_merge_styles(theme_minimal()[['plot.title']], colour = "#6f7170"))

Upvotes: 1

Stan
Stan

Reputation: 995

This can be solved many ways. The shortest might be to override the element_text argument as @eipi10 suggests. This would need to be repeated for each individual plot.

Another way is to create your own custom theme based on an existing theme. The benefit of this approach is that you can reuse your theme once you get it exactly how you like it. Here is an example using theme_fivethiryeight().

The key part is:

   mytheme <- theme_fivethirtyeight() +
  theme(axis.title = element_text(colour = "black" ))

Creating some dummy data to work with:

library("ggplot2")
library("ggthemes")
# make the results reproducible
set.seed(5117)  

start_date <- as.Date("2015-01-01") 
end_date <- as.Date("2017-06-10")

# the by=7 makes it one observation per week (adjust as needed)
dates <- seq(from = start_date, to = end_date, by = 7)
val1 <- rnorm(length(dates), mean = 12.5, sd = 3)

qnt <- quantile(val1, c(.05, .25, .75, .95))

mock <- data.frame(myDate = dates, val1)

p <- ggplot(data = mock, mapping = aes(x = myDate, y = val1)) +
  geom_line() +
  geom_point() +
  geom_hline(yintercept = qnt[1], colour = "red") +
  geom_hline(yintercept = qnt[4], colour = "red") +
  geom_hline(yintercept = qnt[2], colour = "lightgreen") +
  geom_hline(yintercept = qnt[3], colour = "lightgreen") +
  scale_x_date(date_breaks = "6 month", date_labels = "%b-%y") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) 

Here is adding the original theme_fivethirtyeight() for reference:

p + theme_fivethirtyeight()

original theme plot

Creating a custom theme:

mytheme <- theme_fivethirtyeight() +
  theme(axis.title = element_text(colour = "black" ))

Applying the custom theme to the original plot:

p + mytheme

custom theme plot

You can type the theme name (without the "()") at the command prompt to get an idea of what other options are available to customize. Here I highlighted the axis.title = element_blank() that was replaced:

theme_code

Upvotes: 3

Mike H.
Mike H.

Reputation: 14360

You can use %+replace% to replace the specific theme elements you want. For any theme you can retrieve the theme element by using [[. So if you wanted the theme for axis.title from theme_gdocs you would do: theme_gdocs()[["axis.title"]]. This should work for you:

ggplot(mtcars) + geom_point(aes(hp, cyl)) + 
                 theme_fivethirtyeight() %+replace% theme(axis.title = theme_gdocs()[["axis.title"]],
                                                         axis.title.x = theme_gdocs()[["axis.title.x"]],
                                                         axis.title.y = theme_gdocs()[["axis.title.y"]])

enter image description here

I used theme_gdocs as an example but you can replace that with whatever theme you want.

Upvotes: 2

Related Questions