How to add a legend manually by ggplots? - r

For a task I have to make a plot with ggplots with a correct legend.
Well my plot is good, but my legend is not as I want.
I want in my legend a specifing that the triangle is for Sepal, and the plus for Petal.
Can someone help me?
Below is my script.
ggplot(data=iris)+
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color=group), shape=2)+
geom_point(aes(x = Petal.Length, y = Petal.Width, color=group), shape=3)+
xlab("lengte (cm)")+
ylab("breedte (cm)")+
theme(legend.justification=c("left","top"))

I had to make a group variable, but here is an example:
iris$group <- as.factor(sample(c(0,1), nrow(iris), replace=TRUE))
ggplot(data=iris)+
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color=group, shape="Sepal"))+
geom_point(aes(x = Petal.Length, y = Petal.Width, color=group, shape="Petal"))+
xlab("lengte (cm)")+
ylab("breedte (cm)")+
theme(legend.justification=c("left","top"))+
scale_shape_manual(values = c(2,3))

Related

get legend for two different data sets in ggplot

I am trying to create a legend from two different data sets. An example as below
ggplot(data = mtcars,aes(x = mpg, y = wt))+
geom_point(aes(colour = drat))+
geom_line(aes(colour = drat))+
geom_point(data = iris, aes(x = Sepal.Width, y = Petal.Length))+
geom_line(data = iris, aes(x = Sepal.Width, y = Petal.Length),linetype = "dashed")+
scale_color_gradientn(colours=c('red','yellow','green'))
In the first data (mtcars) the color is according to a certain column value (drat). But in the second data (iris) it is just x and y points. How can I get line as the two lines as legend in addition to the color legend which is already present.
Easiest way is to pass names to linetype within the aes() calls. The names become the legend labels. You can then use scale_linetype_manual to set linetypes there:
library(ggplot2)
ggplot(data = mtcars,aes(x = mpg, y = wt))+
geom_point(aes(colour = drat))+
geom_line(aes(colour = drat, linetype = "Cars"))+
geom_point(data = iris, aes(x = Sepal.Width, y = Petal.Length))+
geom_line(data = iris, aes(x = Sepal.Width, y = Petal.Length,
linetype = "Iris"))+
scale_color_gradientn(colours=c('red','yellow','green')) +
scale_linetype_manual(values = c(
"Cars" = "solid",
"Iris" = "dotted"
))

R ggplot geom_label rotate label

I have a plot with labels. I wanted the bounding background box on the label so I switched from using geom_text to geom_label. When I was using the geom_text option I had my angle = 90. Is there a way to do that with geom_label? Or an alternative method to labeling with a background?
Here is some sample code to play with:
ggplot(data = iris,
aes(x = Sepal.Width, y = Petal.Length)) + geom_point(size = 10)+
geom_label(data = iris,
aes(x = Sepal.Width, y = Petal.Length, label = Species),alpha=0.5)
According to the docs
Currently geom_label() does not support the check_overlap argument or the angle aesthetic.
An alternative would be to use ggtext::geom_richtext:
library(ggplot2)
ggplot(
data = iris,
aes(x = Sepal.Width, y = Petal.Length)
) +
geom_point(size = 10) +
ggtext::geom_richtext(aes(label = Species), alpha = 0.5, angle = 90)

Dodge Effect with geom_segment [duplicate]

I did something like this with my data, but despite the transparency the segments are hard to visualise (my data has lot less number of segments than the example below) to see their beginning and end.
require(ggplot2)
ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
y = factor(Species), yend = factor(Species),
size = Sepal.Length)) +
geom_segment(alpha = 0.05) +
geom_point(aes(shape = Species))
Came across this solution, but the lines are criss-crossed. Is there a way to make the jitter produce parallell lines with the points at the tips? I have tried position_dodge instead of position_jitter, but it requires ymax. Can ymax be integrated at all for use with geom_segment?
ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
y = factor(Species), yend = factor(Species))) +
geom_segment(position = position_jitter(height = 0.25))+
geom_point(aes(size = Sepal.Length, shape = Species))
As far as I know, geom_segment does not allow jittering nor dodging. You can add jittering to the relevant variable in the data frame, then plot the jittered variable. In your example, the factor is converted to numeric, then the labels for the levels of the factor are added to the axis using scale_y_continuous.
library(ggplot2)
iris$JitterSpecies <- ave(as.numeric(iris$Species), iris$Species,
FUN = function(x) x + rnorm(length(x), sd = .1))
ggplot(iris, aes(x = Petal.Length, xend = Petal.Width,
y = JitterSpecies, yend = JitterSpecies)) +
geom_segment()+
geom_point(aes(size=Sepal.Length, shape=Species)) +
scale_y_continuous("Species", breaks = c(1,2,3), labels = levels(iris$Species))
But it seems geom_linerange allows dodging.
ggplot(iris, aes(y = Petal.Length, ymin = Petal.Width,
x = Species, ymax = Petal.Length, group = row.names(iris))) +
geom_point(position = position_dodge(.5)) +
geom_linerange(position = position_dodge(.5)) +
coord_flip()
The position argument of geom_segment might be helpful for you, see Slightly change geom_segment's position of x only, but keep position of xend constant

Combine and merge legends in ggplot2 with patchwork (discrete/categorical data)

I arranged 3 ggplot2 plots into a single figure by using the functionality of package patchwork. I tried to collect the legends and they appeared one next to the other. But still, they are 3 separate legends and I expected a single legend. So how can I merge the legends that contain identical values of the same factor variable into a single legend?
Notes:
And I do not want to remove the legends of separate plots by using, e.g., theme(legend.position = "none") in case some additional factor level appears. I expect patchwork specific solution.
A similar question was answered in Combine and merge legends in ggplot2 with patchwork but the data was continuous. And in my case, I have categorical data.
The code:
library(ggplot2)
library(patchwork)
iris_1 <-
ggplot(iris, aes(x = Sepal.Length, fill = Species, color = Species)) +
geom_density(alpha = 0.3, adjust = 1.5)
iris_2 <-
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_point()
iris_3 <-
ggplot(iris, aes(x = Species, y = Sepal.Width, fill = Species)) +
geom_boxplot()
(iris_1 + iris_2 + iris_3) + plot_layout(guides = "collect")
Created on 2020-10-14 by the reprex package (v0.3.0)
Update
I tried using the same aesthetic mappings (fill = Species and color = Species) as it was proposed in the comments below but it had no effect:
library(tidyverse)
library(patchwork)
iris_1 <-
ggplot(iris, aes(x = Sepal.Length, color = Species, fill = Species)) +
geom_density(alpha = 0.3, adjust = 1.5)
iris_2 <-
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species, fill = Species)) +
geom_point()
iris_3 <-
ggplot(iris, aes(x = Species, y = Sepal.Width, color = Species, fill = Species)) +
geom_boxplot(color = "black")
(iris_1 + iris_2 + iris_3) + plot_layout(guides = "collect")
Created on 2020-10-14 by the reprex package (v0.3.0)
Unfortunately setting the same aes is only one condition. patchwork will merge legends only if they are identical. Therefore we have to ensure that the legends are the same for each plot. To this end I add a guides layer which makes the look of each legend the same by setting color, shape, size and alpha. Additionally we have to choose the same glyph for each geom using argument key_glyph. After these adjustments the three legends get merged into one.
library(ggplot2)
library(patchwork)
g <- guides(fill = guide_legend(override.aes = list(color = scales::hue_pal()(3),
shape = c(16, 16, 16),
size = c(1, 1, 1),
alpha = c(1, 1, 1)),))
iris_1 <-
ggplot(iris, aes(x = Sepal.Length)) +
geom_density(aes(fill = Species, color = Species), key_glyph = "point", alpha = 0.3, adjust = 1.5) +
g
iris_2 <-
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(fill = Species, color = Species), key_glyph = "point") +
g
iris_3 <-
ggplot(iris, aes(x = Species, y = Sepal.Width)) +
geom_boxplot(aes(fill = Species, color = Species), key_glyph = "point") +
scale_color_manual(values = c("black", "black", "black")) +
g
(iris_1 + iris_2 + iris_3) + plot_layout(guides = "collect")

Combining geom_point() legends

How do I combine the two legends into one "Species" legend in the code below?
library(ggplot2)
data(iris)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(color = "red", size = Species))
Thanks.
I would prefer visualizing the data in this way if you would like to add the information of the sample size per class.
cat_table <- table(iris$Species)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(color =Species)) +
scale_color_manual(breaks=names(cat_table), labels=paste(names(cat_table), ':', cat_table), values=rainbow(n=length(cat_table)))
Just remove "colour" out of the aesthetics. This seems to be what you are after.
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(size = Species), colour = "red")
If you want to keep colour as an aesthetic, then
you can manually override the colour in the size legend guide
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point(aes(size = Species, colour = "red")) +
guides(colour = FALSE,
size=(guide_legend(override.aes =
list(colour = "red"))))

Resources