How to change default aesthetics in ggplot? - r

Let's say that I would prefer geom_point to use circles (pch=1) instead of solid dots (pch=16) by default. You can change the shape of the markers by passing a shape argument to geom_point, e.g.
ggplot(diamonds, aes(depth, carat, colour=cut)) + geom_point(shape=1)
ggplot(diamonds, aes(depth, carat, colour=cut)) + geom_point(shape=16)
but I can't figure out how to change the default behaviour.

Geom (and stat) default can be updated directly:
update_geom_defaults("point", list(shape = 1))
ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point()

One way to do it (although I don't really like it) is to make your own geom_point function. E.g.
geom_point2 <- function(...) geom_point(shape = 1, ...)
Then just use as normal:
ggplot(diamonds, aes(depth, carat, colour=cut)) + geom_point2()
Or if you want you can override the function geom_point():
geom_point <- function(...) {
ggplot2::geom_point(shape = 1, ...)
}
This might be considered bad practice but it works. Then you don't have to change how you plot:
ggplot(diamonds, aes(depth, carat, colour=cut)) + geom_point()

Related

Why does geom_jitter replicates black points when we use aes colour?

I came across this issue while analyzing my data and I was able to replicate it with the example of the official ggplot reference.
This code creates black points that seem to be the original points before jitter was applied with collors:
ggplot(mpg, aes(cyl, hwy)) +
geom_point() +
geom_jitter(aes(colour = class))
However, this code works fine, it doesn't show the black points:
p <- ggplot(mpg, aes(cyl, hwy))
p + geom_point()
p + geom_jitter(aes(colour = class))
I was thinking it may be related to geom_point printing the black dots before geom_jitter, but if this is the case, why does it work fine in the second example, which follows the same order?
This is the image of the black points
geom_jitter is merely a convenience function, it is calling geom_point under the hood. Because of this, your use of p + geom_point() + geom_jitter(aes(color=class)) is actually the same as
ggplot(ggplot2::mpg, aes(cyl, hwy)) +
geom_point() +
geom_point(aes(color = class), position = "jitter")
which is plotting the same points twice. You can clarify this a little by changing the color of the original points:
ggplot(ggplot2::mpg, aes(cyl, hwy)) +
geom_point(color = "red") +
geom_jitter(aes(color = class))
If you want jittered points, use either geom_point(position = "jitter") or geom_jitter(), not both.

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.

Legend in not mapping linetype when geom_errorbar is used

Consider the data:
enter code here
group <- rep(c("a", "b"), each=10)
res <- c(sample(20:30,10,T),sample(60:80,10,T) )
sd <- rnorm(20,2)
t <- rep(1:10,2)
df <- data.frame(t=t,group=group, res=res, sd=sd)
From that I want this plot:
ggplot(df, aes(x=t, y=res,
group=group,
colour=group,
shape=group ), linetype="solid")+
geom_point()+
geom_errorbar(aes(ymin=res-sd, ymax=res+sd))+
geom_line(aes(linetype=group))
The problem:
The legend is NOT mapping the aesthetics linetype.
It is doing correctly for shape and colour.
I also tried setting the linetype as overall mapping and linetype="solid" in geom_errorbar, but the result was the same. See code bellow.
ggplot(df, aes(x=t, y=res,
group=group,
colour=group,
shape=group,
linetype=group))+
geom_point()+
geom_errorbar(aes(ymin=res-sd, ymax=res+sd), linetype="solid")+
geom_line()
For obvious reasons I don't want errorbars with different line types.
The reason for this many mappings to the same variable is to make it beautifull on screen and black an white print friendly.
How can I do this plot and have the legend mapping the linetype too?
Here is one option:
ggplot(df, aes(x=t, y=res,
group=group,
colour=group,
shape=group,
linetype=group))+
geom_point()+
geom_errorbar(aes(ymin=res-sd, ymax=res+sd,
linetype = NULL)) + #remove the mapping
geom_line()

incorrect linetype in geom_vline with legend in r ggplot2

I am trying to display the xvar median as a dotted line & show it in the legend. Here's my code:
require(ggplot2)
require(scales)
medians_mtcars <- data.frame("wt.median"=median(mtcars$wt))
# legend shows but linetype is wrong (solid)
p <- ggplot(mtcars, aes(wt, mpg))
p <- p + geom_point()
p <- p + geom_vline(aes(xintercept=wt.median, linetype="dotted"),
data=medians_mtcars, show_guide=TRUE)
p
I also tried:
# linetype is correct but legend does not show
p <- ggplot(mtcars, aes(wt, mpg))
p <- p + geom_point()
p <- p + geom_vline(aes(xintercept=wt.median),
data=medians_mtcars, show_guide=TRUE, linetype="dotted")
p
Would have liked to post the plot images, but haven't crossed the reputation threshold yet.
There were 2 other posts on this forum that comes close to this topic but does not offer a solution to this problem:
Add vline to existing plot and have it appear in ggplot2 legend?
;
Incorrect linetype in legend, ggplot2 in R
I am using ggplot2 version 1.0.0
What am I doing wrong ?
Thanks in advance
If you need to show linetype in legend and also change it then inside aes() you can just write name for that linetype (as you have only one line) and then change linetype with scale_linetype_manual().
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
geom_vline(aes(xintercept=wt.median, linetype="media"),
data=medians_mtcars, show_guide=TRUE)+
scale_linetype_manual(values="dotted")
If you really want to type linetype in aes() and also get correct legend then you should use scale_linetype_identity() with argument guide="legend".
ggplot(mtcars, aes(wt, mpg)) +
geom_point() +
geom_vline(aes(xintercept=wt.median, linetype="dotted"),
data=medians_mtcars,show_guide=TRUE)+
scale_linetype_identity(guide="legend")

Seemingly incorrect guide color when geom_line() and geom_segment() are used together

I'm drawing some line segments on top of a plot that uses geom_line(). Surprisingly, the guide (legend) colors for geom_line() are drawn as the color of the last element I add to the plot - even if it is not the geom_line(). This looks like a bug to me, but it could be expected behavior for some reason I don't understand.
#Set up the data
require(ggplot2)
x <- rep(1:10, 2)
y <- c(1:10, 1:10+5)
fac <- gl(2, 10)
df <- data.frame(x=x, y=y, fac=fac)
#Draw the plot with geom_segment second, and the guide is the color of the segment
ggplot(df, aes(x=x, y=y, linetype=fac)) +
geom_line() +
geom_segment(aes(x=2, y=7, xend=7, yend=7), colour="red")
Whereas if I add the geom_segment first, the colors on the guide are black as I would expect:
ggplot(df, aes(x=x, y=y, linetype=fac)) +
geom_segment(aes(x=2, y=7, xend=7, yend=7), colour="red") +
geom_line()
Feature or bug? If the first, can someone explain what's happening?
Feature(ish). The guide that is drawn is a guide for linetype. But, it has to be drawn in some color to be seen. When the color is not specified by an aesthetic mapping, ggplot2 draws it in a color that is consistent with the plot. I'm speculating that the default is whatever last color was used. That is why you are seeing differences when you plot them in a different order.
However, you can control these details of the legend.
ggplot(df, aes(x=x, y=y, linetype=fac)) +
geom_line() +
geom_segment(aes(x=2, y=7, xend=7, yend=7), colour="red") +
scale_linetype_discrete(guide=guide_legend(override.aes=aes(colour="blue")))

Resources