ggplot theme_set() only works intermittently - r

I'll often set a theme early on in a script, with a specific base font size.
# CODE BLOCK 1
library(tidyverse)
ggplot(mtcars, aes(cyl, mpg)) +
geom_col() +
theme_set(theme_bw(base_size = 20))
Then I'll want to switch the theme and the font size for a different plot later on in my script. I will try to accomplish this with code like below.
# CODE BLOCK 2
ggplot(mtcars, aes(factor(cyl))) +
geom_bar() +
theme_set(theme_gray(base_size = 6))
I just ran these two code blocks on a fresh R session and when I ran code block 2 the theme and base font size did not change to the arguments listed above. I immediately ran code block 2 again and the theme and font size changed to the arguments shown above. Why is theme_set() only working intermittently?
My session info follows:
OS: Windows 7 64 bit
R: 3.4.4
R Studio: 1.1.442
ggplot2: 2.2.1.9000

Please try this. See also here ?theme_set
theme_set(theme_bw(base_size = 20))
ggplot(mtcars, aes(cyl, mpg)) +
geom_col()
theme_set(theme_gray(base_size = 6))
ggplot(mtcars, aes(factor(cyl))) +
geom_bar()
Or simply without the theme_setfunction
ggplot(mtcars, aes(factor(cyl))) +
geom_bar() +
theme_gray(base_size = 6)

Related

ggrepel::geom_text_repel not working in large mode/Rstudio notebook output (nor with cowplot)

I was wondering if anyone knew why this is happening. Here is a quick example of the code and screenshots.
library(ggplot2)
iris$randomratio <- iris$Sepal.Length/iris$Sepal.Width
plot_iris <- ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color = Species)) +
geom_point() +
theme_light() +
ggrepel::geom_text_repel(data=subset(iris, randomratio > 2.7),
aes(Sepal.Length, Sepal.Width, label= Species))
plot_iris
cowplot::plot_grid(plot_iris, plot_iris, label = c('A', 'B'))
Now when I do this in an RMD file I get the points labelled that I want (right) But when I try to do this in the Rstudio notebook output I get the following:
NB It doesn't work with ggplot or cowplot. With cowplot it doesn't work in the regular file as well.
Does anyone know how I can fix this?
I see a warning with 'cowplot', but a figure with text labels.
Warning message:
In as_grob.default(plot) :
Cannot convert object of class character into a grob.
I see no warning with 'patchwork'. You need to be aware that with geom_text() if want to avoid text overlapping the points, instead of sub-setting the data you have to set labels to "". Reducing the size of the labels helps with the repulsion. Collecting identical legends when composing the plot gives also a bit more room. The code below renders well to a HTML notebook under R 4.1.0 and latest versions of the packages.
library(ggplot2)
library(patchwork)
iris$randomratio <- iris$Sepal.Length/iris$Sepal.Width
iris$label <- ifelse(iris$randomratio > 2.7, as.character(iris$Species), "")
plot_iris <-
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color = Species)) +
geom_point() +
theme_light() +
ggrepel::geom_text_repel(aes(label = label), size = 3, min.segment.length = 0)
plot_iris + plot_iris +
plot_annotation(tag_levels = 'A') +
plot_layout(guides = 'collect')
Created on 2021-08-03 by the reprex package (v2.0.0)

Animating with ggplot and gganimate

I'm trying to learn about animating plots with gganimate, and I'm wondering if someone has a tip for the problems I'm running into. In an effort to make things simple, I'm doing this by creating a new project in RStudio Cloud, installing the ggplot2, gganimate, and datasauRus packages, and following this example from Isaac Faber:
library(datasauRus)
library(ggplot2)
library(gganimate)
ggplot(datasaurus_dozen, aes(x=x,y=y)) +
geom_point() +
theme_minimal() +
transition_states(dataset,3,1) +
ease_aes()
This creates a series of .PNG files but I cannot see an animation. Some seem to suggest that I can see it using the "print" function, but this does not work either.
I have also been unable to export this as a .GIF, although I have followed the advice given here. Specifically, the magick packages does not work for me (I get the same error about my images not being magick image objects), and when I try the following code:
p <- ggplot(datasaurus_dozen, aes(x=x,y=y)) +
geom_point() +
theme_minimal() +
transition_states(dataset,3,1) +
ease_aes()
anim <- animate(p)
anim_save("myfilename.gif",anim)
R tells me that The
animation object does not specify a save_animation method.
I've been unable to find examples or documentation that tells me how to specify a save_animation method. If anyone has advice on this topic, it would be greatly appreciated!
you're doing one step too many:
library(datasauRus)
library(ggplot2)
library(gganimate)
p <- ggplot(datasaurus_dozen, aes(x=x,y=y)) +
geom_point() +
theme_minimal() +
transition_states(dataset,3,1) +
ease_aes()
anim_save("myfilename.gif",p)
I solved this by specifying the gifski_renderer() in animate():
library(tidyverse)
library(gganimate)
library(gapminder)
g <- ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
geom_point(alpha = 0.7, show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
scale_x_log10() +
facet_wrap(~continent) +
# Here comes the gganimate specific bits
labs(title = 'Year: {frame_time}', x = 'GDP per capita', y = 'life expectancy') +
transition_time(year) +
ease_aes('linear')
animate(g, height=400, width=600, renderer=gifski_renderer())
anim_save("gapminder.gif", g)
Note: this is the default renderer for animate(), but somehow needed to be specified explicitly. After doing it the first time, I no longer need to set it, a behavior I can't explain.

Change geom default aesthetics as part of theme component only

For a custom ggplot2 theme I'd like to change the default aesthetic of some geom, say I want red dots instead of black dots.
From this answer I know we can change defaults for a geom using the function update_geom_default but I wonder if it is possible to change the colour only when we call theme_red_dots?
Example of my naive attempt:
library(ggplot2)
theme_red_dots <- function(...) {
update_geom_defaults("point", list(colour = "red"))
theme_minimal() +
theme(...)
}
Looks good here:
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
theme_red_dots()
But I'd like the points to be black again when I call
ggplot(mtcars, aes(mpg, disp)) +
geom_point()
Thanks in advance!
Below is an example of why I thought this could be useful. We can change panel.background to be black fairly easy but this would make it impossible to see the points if we don't map an aesthetic to colour. (The usefulness of this theme_black can certainly be discussed, but I would like to avoid an argument about that.)
theme_black <- function(...) {
theme_minimal() +
theme(panel.background = element_rect(fill = "black")) +
theme(...)
}
# update_geom_defaults("point", list(colour = "black"))
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
theme_black()
Changing the colour of the points inside geom_point() is an option here (see #zx8754 answer), but this requires the user of theme_black() to change it, while I am wondering if there is a way to do this right inside theme_*.
Another solution is to detach and reattach ggplot2 (apparently you can do this within custom ggplot2 theme function).
library(ggplot2)
theme_red_dots <- function(...) {
# wanted theme
update_geom_defaults("point", list(colour = "red"))
# Plot
p <- theme_minimal() +
theme(...)
# Detach and reattach ggplot2
detach("package:ggplot2", unload = TRUE); library(ggplot2)
# Return wanted plot
return(p)
}
# red dots
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
theme_red_dots()
# black (default) dots
ggplot(mtcars, aes(mpg, disp)) +
geom_point()
Works with wanted theme_black too:
theme_black <- function(...) {
update_geom_defaults("point", list(colour = "red"))
p <- theme_minimal() +
theme(panel.background = element_rect(fill = "black")) +
theme(...)
detach("package:ggplot2", unload = TRUE); library(ggplot2)
return(p)
}
# Plots with black background
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
theme_black()
# Plots with default background
ggplot(mtcars, aes(mpg, disp)) +
geom_point()
The released version of ggplot2 doesn't currently offer a way to do this. However, this is a fairly old feature request and has been under development since the summer of 2018.
Instead of changing defaults, make custom geom_point:
library(ggplot2)
# make custom geom with red as default
geom_point_red <- function()geom_point(col = "red")
ggplot(mtcars, aes(mpg, disp)) +
geom_point_red()
As my reputation won't allow me to comment:
#PoGibas:
An issue about detaching and re-attaching ggplot2 is that if other packages are loaded that require it, e.g. rstan, it won't work and return an error.

Multiple gganimate plots side by side

I would like to display animations made by the package gganimate side by side or at least in the same document.
Plots to work with:
library(ggplot2)
library(gganimate)
anime_one <-
ggplot(mtcars, aes(factor(cyl), mpg)) +
geom_boxplot() +
# Here comes the gganimate code
transition_states(
gear,
transition_length = 2,
state_length = 1
) +
enter_fade() +
exit_shrink() +
ease_aes('sine-in-out')
anime_two <-
ggplot(mtcars, aes(factor(cyl), mpg, fill = factor(cyl))) +
geom_boxplot() +
# Here comes the gganimate code
transition_states(
gear,
transition_length = 2,
state_length = 1
) +
enter_fade() +
exit_shrink() +
ease_aes('sine-in-out')
First attempt:
library(patchwork)
anime_one + anime_two
Error in UseMethod("ggplot_gtable") :
no applicable method for 'ggplot_gtable' applied to an object of class
"gganim_built"
Second attempt:
library(patchwork)
animate(anime_one+anime_two)
This actually renders and doesn't give an error, but the result is an animation of only the last "gganim_built" object (here anime_two)
Third attempt (Works, but not really what I am looking for)
The only halfway solution I have found is to include everything in a Rmarkdown document, and then make codecunks with animation calls (only one animation call pr codechunk otherwise it doesn't work), and finally knit the document to HTML:
```{r}
animate(anime_one)
```
```{r}
animate(anime_two)
```
Has anyone managed to make gganimate objects appear side by side?
Thanks in advance.
Seems that gganimate help docs are being rewritten and maybe you can find a solution about "animation composition" here:
https://github.com/thomasp85/gganimate/wiki/Animation-Composition
Under the title "Placing Animations side-by-side with magick" there's a method to do such thing.
Hope this help

How to set linetype for geom_vline in a faceted plot?

The following code works like a charm:
foo = data.frame(x=c(1,2,3),
y=c(4,5,6),
lt=c('dotted', 'dashed', 'dotdash'))
ggplot(foo, aes(x,y)) + geom_point() +
geom_vline(aes(xintercept=x, linetype=lt))
The following code drops linetype. Why?
ggplot(foo, aes(x,y)) + geom_point() +
geom_vline(xintercept=3, aes(linetype=lt)) +
facet_wrap(~lt)
I am using ggplot 0.9.3.1 in Rstudio.
I can confirm your problem and also that Sandy's comment fixes it for me, using ggplot2 1.0 in R 3.1.2:
geom_vline(aes(xintercept = 3, linetype = lt))
However I still think this is a bug in (maybe just the documentation for) geom_vline. I think xintercept should be listed as a required aesthetic with a default value of 0. Notably, the code below "works" -- the lines have the correct hashing at the default x location of 0:
ggplot(foo, aes(x,y)) +
geom_point() +
geom_vline(aes(linetype=lt)) +
facet_wrap(~lt)
So the problem seems to be that when required aesthetics are supplied outside of aes(), the arguments inside of aes() are ignored. This is different than other functions. For example,
ggplot(foo) + geom_point(x=1, aes(y=y))
gives an error but
ggplot(foo) + geom_point(aes(x=1, y=y))
does not. As far as I'm concerned, ideal behavior would be for geom_vline() to behave the same way as geom_point() in this regard.

Resources