Can Ggplot Theme Formatting Be Saved as an Object

Can ggplot theme formatting be saved as an object?

You can make a theme object without any problems, e.g:

mytheme<-theme(panel.background=element_rect(colour="green"))

It is even easier, if this is your standard theme to type

old_theme<- theme_update(panel.background=element_rect(colour="green"))

In the former case you write:

ggplot(...)+mytheme

while in the latter, because your custom theme is now the standard theme, it is only necessary to type:

ggplot(...)

Error: Don't know how to add RHS to a theme object when saving theme formatting in R

Hi welcome to stackoverflow. You cannot change labels within the theme call, nor can you save a theme with labels that's why you get that error. This happens because labs() is not a theme. Before saving the theme, ggplot checks if the theme is a theme and returns that error if it isn't.

is.theme(labs(caption="Graphics: XYZ\nSource: ABC"))
[1] FALSE

Save the theme and then add the labels separately.

my_theme <- theme(plot.caption=element_text(size=20, vjust = 0.55,
hjust = 0.99, colour = "black", family = "Eurostile"),
plot.background = element_rect(fill = "#DCDCDC"),
panel.background = element_rect(colour = "#DCDCDC"),
axis.text = element_text(colour = "black", size = 20))

# assuming you plot is saved as p

p + my_theme + labs(caption="Graphics: XYZ\nSource: ABC")

That saves the theme and then you can add the labels to your plot when you add the theme. You can also save labels to the plot object p with the calls to ggplot and geom etc.

Store custom ggplot styles in object

You can create a list of customizations and then apply that to each plot. For example:

customPlot = list(
theme(plot.margin = unit(c(1,1,2,2), "cm"),
axis.text.x = element_text(vjust=0.5, size=20),
plot.title=element_text(size=20, vjust=2),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.title.x = element_blank(), axis.title.y = element_blank(),
panel.background = element_rect(fill = "#D9D9D9")),
coord_cartesian(ylim = c(0, 1)),
scale_fill_manual(values=c("#05f2ae", "#17b0c4"))
)

ggplot(mdf, aes (x=group, y=value, fill = variable)) +
geom_bar(stat="identity", position="dodge", alpha = 0.8) +
geom_bar(stat="identity", position="dodge", color = "#A9A9A9", alpha = 0.8) +
geom_text(aes(x=group, y=value, ymax=value, label=value),
position=position_dodge(1), vjust=-1, size=12) +
customPlot

GGPlot2 Preset - Creating a function with certain ggplot2 aesthetics options

You can store things to be added to a plot in a list. You can then re-use this list by adding it to a plot.

library(ggplot2)
library(ggthemes)
library(magrittr)

common_options <- list(
scale_fill_viridis_d(name = "", option = "inferno", begin = 0.3, end = 0.7, direction = -1),
scale_shape_tableau(),
theme_economist(),
theme(plot.background = element_rect(fill = "white"),
plot.title = element_text(hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5),
axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1),
plot.margin = unit(c(1,1,1,1), "cm"))
)

df1 <- data.frame(name = c("name1","name2","name3","name4"),
variable = c("var1","var1","var2","var2"),
value = c(15,16,17,18))

df1 %>%
ggplot(aes(x = name, y = value, fill = variable)) +
geom_bar(stat = "identity", position = position_stack()) +
labs(title = "Plot Title",
subtitle = "month 1",
x="",
y="Count") +
common_options

Sample Image

Created on 2021-07-20 by the reprex package (v1.0.0)

can you pre-compose ggplot elements for repeated use?

Following this answer, you can put all these into a list and then add it via + to your plot. This list can include theme elements.

my_xaxis = list(xlab("My axis title"),
scale_x_discrete( limits = my_predefined_category_order ),
theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) )

Here's what it could look like in practice.

my_predefined_category_order = c("8", "6", "4")
my_xaxis = list(xlab("My axis title"),
scale_x_discrete( limits = my_predefined_category_order ),
theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) )

p = ggplot(mtcars, aes(x = factor(cyl), y = mpg)) +
geom_point()
p + my_xaxis

Sample Image

Conditionally modify ggplot theme based on presence of facets?

I think Oliver was thinking in the correct direction.

I don't think the theme_custom function is the correct place to check the plot for conditional theming, because theme functions are mostly agnostic about the precise plot that they are added to.

Instead, I think the appropriate place to check the plot is when the theme is added to the plot. You could write a theme function like the following, which sets a different class to the output.

theme_custom <- function() {
out <- theme_minimal()
class(out) <- c("conditional_theme", class(out))
out
}

Now everytime a theme is added to a plot, this is done through the ggplot_add.theme function, which we can rewrite for the conditional_theme class. In my opinion, the correct way to check if a plot is facetted, is to check the class of the plot$facet slot, which can be FacetGrid, FacetWrap etc when a proper facet is added and defaults to FacetNull when no facet is set.

ggplot_add.conditional_theme <- function(object, plot, object_name) {
if (!inherits(plot$facet, "FacetNull")) {
object <- object + theme(panel.border = element_rect(colour = "grey50", fill = NA))
}
plot$theme <- ggplot2:::add_theme(plot$theme, object, object_name)
plot
}

And now the use cases should work as intended:

ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
facet_wrap(vars(cyl)) +
theme_custom()

Sample Image

ggplot(mtcars, aes(mpg, wt)) +
geom_point() +
theme_custom()

Sample Image

The only downside is that you would literally have to add the theme to the plot every time and you can't use the theme_set(theme_custom()) to have this apply to any plot in the session.



Related Topics



Leave a reply



Submit