How to repel labels in ggplot - r

If the labels in the example below were to be overlapping, how could we implement a repel option? Thanks!
means <- df %>%
group_by(cyl) %>%
summarize(across(c(wt, mpg), mean))
ggplot(df) +
aes(x=wt, y=mpg, color=cyl, shape=cyl) +
geom_point() +
geom_point(size=4, data=means) +
geom_label(aes(label=cyl), color="black", data=means) -> fig
fig
If I add the geom_label_repel() from the ggrepel package
fig + geom_label_repel()
I get the error:
geom_label_repel requires the gollowing missing aesthetics: label

You need to map label so that geom_label_repel "sees" it. It doesn't have direct view of the mapping from other geoms. Just itself and the top ggplot call. You thus have two options.
Directly within the function
geom_label_repel(mapping = aes(label = cyl))
or in the top ggplot call
ggplot(data = df, mapping = aes(label = cyl)) +
Note that you'll probably have to specify data as Vincent mentioned in the comment if you want to label the means points.

Related

Subdividing jitter points in ggplot

I'm having difficulty getting geom_jitter to separate my data points by a third variable (phase).
I'd like for each bar in this 2x2 graph to have its own set of jittered data points for each phase condition.
Right now the points are grouped between the two phase bars (sorry couldn't upload the image -- don't have my 10 posts yet).
I know I'm missing something in the geom_jitter aes, but not sure what it is -- fill=phase is not doing the trick.
ggplot(datalong, aes(grp, score)) +
geom_bar(stat = "summary", fun.y = "mean", aes(fill=phase), position = "dodge", alpha = .5) +
geom_jitter(inherit.aes = FALSE, aes(grp, score, fill=phase), position = position_jitter(0.2))
The default shape for points does not take the fill aesthetic
Compare
library(ggplot2)
ggplot(mtcars, aes(mpg, disp, fill = gear)) +
geom_jitter()
ggplot(mtcars, aes(mpg, disp, color = gear)) +
geom_jitter()
ggplot(mtcars, aes(mpg, disp, fill = gear)) +
geom_jitter(shape = 21)
Created on 2020-07-09 by the reprex package (v0.3.0)
Found a solution using:
geom_point(position=position_jitterdodge())
This seems to jitter and dodge to separate the points.

How to use with plot_grid from cowplot

I want to combine several ggplot2 charts into one using cowplot::plot_grid(). From its documentation:
?plot
Arguments
...
List of plots to be arranged into the grid. The plots can be objects of one of the following classes: ggplot, recordedplot, gtable, or alternative can be a function creating a plot when called (see examples).
So, If I input a list of ggplot2 objects to plot_grid(), it should combine those plots into one, right?
So why won't this work?
p1 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
p2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
list(p1, p2) %>%
map(plot_grid)
See the documentation of map (?map), it states that:
.x A list or atomic vector.
.f A function, formula, or atomic vector.
It means the function you provided for .f will be applied to every elements in .x. So the following code
list(p1, p2) %>% map(plot_grid)
is the same as the following code
plot_grid(p1)
plot_grid(p2)
,which is probably not what you want.
What you want is probably this
plot_grid(p1, p2)
Or this
plot_grid(plotlist = list(p1, p2))
You want do.call(), not map(), to pass a list of arguments to a function. For your example above:
library(ggplot2)
p1 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
p2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plots <- list(p1, p2)
do.call(cowplot::plot_grid, plots)

ggplotly: log argument cancels axis labels

I just discovered the newish ggplotly function that makes ggplot2 graphs into interactive plotly visualizations. This is great. But I also ran into an odd effect, possibly a bug.
If I use the log= argument to change the axis scales, the axis labels disappear. log="x" will cause the x axis label to disappear, log="y" will cause the y axis label to disappear, and log="xy" will cause both to disappear.
The same thing happens if I use scale_x_log10() and scale_y_log10() functions instead of the log argument.
Is there a workaround for this?
Example (y axis label is visible, x axis label disappears):
qplot(wt, mpg, data=mtcars, colour=factor(cyl), log="x")
ggplotly()
or
qplot(wt, mpg, data=mtcars, colour=factor(cyl)) + scale_x_log10()
ggplotly()
You can get axis names if you supply them as arguments to scale_... function.
qplot(wt, mpg, data=mtcars, colour=factor(cyl)) + scale_x_log10("wt")
ggplotly()
or maybe this?
ggplot(data = mtcars, aes(x = log10(wt), y=mpg, colour = factor(cyl))) +
geom_point() +
scale_x_continuous("wt, log10-scaling")
ggplotly()
Maybe this:
gg <- ggplot(mtcars, aes(x=wt, y=mpg)) +
geom_point() + coord_trans(y="log10")
ggplotly(gg) %>% layout(yaxis = list(type="log", autorange=TRUE))

How to fill boxes in geom_point legend with color of points, not just increasing their size?

I'm having a similar problem as described in here under "2- After having the two legends...", but instead of increasing the point size (which eventually also enlarges the legend itself), I would like fill each box in the legend with the corresponding color. Like in a bar plot's legend. Data & code examples here.
Looking through several other questions here, the ggplot docu, etc., I tried variations of code-snippets I found, but couldn't figure out a solution. The legend always retained the point symbols.
Therefore: If possible, how to tweak or replace the legend of a point/scatter/bubble plot so that it looks like the legend of a bar plot? Or, more generally, how to replace the legend of a given geom in ggplot2 with that of a different one? Thank you for any hints!
Edit: Example with mtcars data
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl), size = qsec))
p
Adding what I gathered from other SO-answers...
p <- p + guides(colour = guide_legend(override.aes = list(fill = unique(mtcars$cyl))))
p
...keeps the points, instead of expanding the color to fill the legend box, no matter arguments and datasources I try for guides() and list().
On the other hand:
ggplot(mtcars, aes(wt, mpg)) + geom_bar(aes(fill = factor(cyl)), stat="identity")
...draws nicely color-filled boxes to the legend. That's what I'm trying to do for a bubble plot.
You won't be able to get a fill-type legend per se, but you can easily emulate it:
ggplot(mtcars, aes(wt, mpg)) +
geom_point(aes(colour = factor(cyl), size = qsec)) +
guides(col = guide_legend(override.aes = list(shape = 15, size = 10)))

How would you plot a box plot and specific points on the same plot?

We can draw box plot as below:
qplot(factor(cyl), mpg, data = mtcars, geom = "boxplot")
and point as:
qplot(factor(cyl), mpg, data = mtcars, geom = "point")
How would you combine both - but just to show a few specific points(say when wt is less than 2) on top of the box?
If you are trying to plot two geoms with two different datasets (boxplot for mtcars, points for a data.frame of literal values), this is a way to do it that makes your intent clear. This works with the current (Sep 2016) version of ggplot (ggplot2_2.1.0)
library(ggplot2)
ggplot() +
# box plot of mtcars (mpg vs cyl)
geom_boxplot(data = mtcars,
aes(x = factor(cyl), y= mpg)) +
# points of data.frame literal
geom_point(data = data.frame(x = factor(c(4,6,8)), y = c(15,20,25)),
aes(x=x, y=y),
color = 'red')
I threw in a color = 'red' for the set of points, so it's easy to distinguish them from the points generated as part of geom_boxplot
Use + geom_point(...) on your qplot (just add a + geom_point() to get all the points plotted).
To plot selectively just select those points that you want to plot:
n <- nrow(mtcars)
# plot every second point
idx <- seq(1,n,by=2)
qplot( factor(cyl), mpg, data=mtcars, geom="boxplot" ) +
geom_point( aes(x=factor(cyl)[idx],y=mpg[idx]) ) # <-- see [idx] ?
If you know the points before-hand, you can feed them in directly e.g.:
qplot( factor(cyl), mpg, data=mtcars, geom="boxplot" ) +
geom_point( aes(x=factor(c(4,6,8)),y=c(15,20,25)) ) # plot (4,15),(6,20),...
You can show both by using ggplot() rather than qplot(). The syntax may be a little harder to understand, but you can usually get much more done. If you want to plot both the box plot and the points you can write:
boxpt <- ggplot(data = mtcars, aes(factor(cyl), mpg))
boxpt + geom_boxplot(aes(factor(cyl), mpg)) + geom_point(aes(factor(cyl), mpg))
I don't know what you mean by only plotting specific points on top of the box, but if you want a cheap (and probably not very smart) way of just showing points above the edge of the box, here it is:
boxpt + geom_boxplot(aes(factor(cyl), mpg)) + geom_point(data = ddply(mtcars, .(cyl),summarise, mpg = mpg[mpg > quantile(mpg, 0.75)]), aes(factor(cyl), mpg))
Basically it's the same thing except for the data supplied to geom_point is adjusted to include only the mpg numbers in the top quarter of the distribution by cylinder. In general I'm not sure this is good practice because I think people expect to see points beyond the whiskers only, but there you go.

Resources