How to add labels to multiple ggplot graphs (A, B, C) - r

I am trying to add the labels A, B, and C to the top left hand corner of each of these graphs. I have tried cowplot::draw_plot_label(), but nothing seems to work. Can anyone help?
These A, B and C labels are not the main title of each plot.
# Packages
library(ggplot2)
library(gridExtra)
library(cowplot)
# 1st plot
p1 <- ggplot(data = new_data %>%
filter(Species =="Sharksucker_Remora")) +
scale_colour_manual(values=c(Sharksucker_Remora="black"), labels = c("Sharksucker Remora")) +
geom_line(mapping = aes(x = Date, y = Proportion, group = Species, colour = Species)) +
xlab("") +
ylab("Proportion") +
theme(legend.position="top") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) + labs(colour = ~italic(M.alfredi)~"Hitchhiker Species:") +
theme(legend.key=element_blank())
# 2nd plot
p2 <- ggplot(data = new_data %>%
filter(Species !="Sharksucker_Remora")) +
geom_line(mapping = aes(x = Date, y = Proportion, group = Species, colour = Species)) +
scale_colour_manual(values=c(Golden_Trevally="goldenrod2", Red_Snapper="firebrick2", Juvenile_Remora="darkolivegreen3"), labels = c("Juvenile Remora", "Golden Trevally", "Red Snapper")) +
xlab("") + ylab("Proportion") + labs(colour = "") + theme(legend.position="top") + theme(legend.key=element_blank()) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
# 3rd plot
p3 <- ggplot(data = new_data_counts) +
geom_bar(mapping = aes(x = Date, y = Count), stat =
'identity') +
xlab("Date (2015-2019)") + ylab("Total"~italic
(M.alfredi)~"Sightings") +
draw_plot_label(label =c("C") + theme(axis.text.x =
element_text(angle = 90, vjust = 0.5, hjust = 1))
# The grid
grid.arrange(p1,p2,p3)

I suggest you use labs(..., tag = ...) and theme(plot.tag = element_text()).
The code show how you can format the main title (here centered with hjust = 0.5) and the tag inside the theme() function. See the reproducible example, below:
# Packages
library(ggplot2)
library(gridExtra)
# library(cowplot) # not necessary here
# Plots
p1 <- ggplot() +
labs(title = "plot 1", tag = "A") +
theme(plot.title = element_text(hjust = 0.5),
plot.tag = element_text())
p2 <- ggplot() +
labs(title = "plot 2", tag = "B") +
theme(plot.title = element_text(hjust = 0.5),
plot.tag = element_text())
grid.arrange(p1, p2)
If you want the tag (A, B, C) to be inside the plotting area, this post suggest to use plot.tag.position = c(x, y). See for example:
p3 <- ggplot() +
labs(title = "plot 3", tag = "C") +
theme(plot.title = element_text(hjust = 0.5),
plot.tag = element_text(),
plot.tag.position = c(0.1, 0.8))
p3

Have you tried the package egg?
https://cran.r-project.org/web/packages/egg/vignettes/Overview.html
library(tidyverse)
library(magrittr)
data <- list()
for(i in 1:6) data[[i]] <- rnorm(100,0,1)
data %<>% bind_cols() %>% setNames(paste0("var",1:6))
p1 <- ggplot(data,aes(x = var1, y = var2)) + geom_point()
p2 <- ggplot(data,aes(x = var3, y = var4)) + geom_point()
p3 <- ggplot(data,aes(x = var5, y = var6)) + geom_point()
egg::ggarrange(p1,p2,p3,ncol = 1,
labels = c("A","B","C"))

Another option is using the patchwork package with plot_annotation which has the tag_levels argument which gives the possibility to add tags like letters or numbers. First a reproducible example with letters:
library(patchwork)
library(ggplot2)
p1 <- ggplot(mtcars) +
geom_point(aes(hp, disp)) +
ggtitle('Plot 1')
p2 <- ggplot(mtcars) +
geom_boxplot(aes(gear, mpg, group = gear)) +
ggtitle('Plot 2')
p1 + p2 & plot_annotation(tag_levels = 'A')
Created on 2022-08-21 with reprex v2.0.2
Another option with numbers where you change the tag_levels to "1" like this:
p1 + p2 & plot_annotation(tag_levels = '1')
Created on 2022-08-21 with reprex v2.0.2
As you can see, the tags have letters or numbers. Check the links above for more information and options.

Related

How to add legend to combined ggplot2 (different values)

I need to add a legend to my combined ggplot but don't seem to succeed. The data is made up from three different values of which "targeted" and "non targeted" are in one plot and "response" in the other. I would like to add the legend at the bottom of the combined plot.
Thanks in advance
Output of my current code
A <- ggplot(placeholder) +
geom_line(aes(x=date, y= targeted), color='#0072b2', group= 1, size=1.25) +
geom_line(aes(x=date, y= non_targeted), color='#d55e00' , group= 1, size=1.25) +
theme(axis.text.x = element_text(angle = 90)) +
labs(y= "Y1", x = "Date") + theme_classic() +
theme(axis.text.x = element_text(angle = 90))
A
B <- ggplot(media_analysis) +
geom_line(aes(x=date, y= nuisance_reports), color='#f0e442', group= 1, size=1.25) +
theme(axis.text.x = element_text(angle = 90)) +
labs(y= "Y2", x = "Date") + theme_classic() +
theme(axis.text.x = element_text(angle = 90))
B
combined <- plot_grid(A, B,
labels = c("A", "B"),
ncol = 2, nrow = 1)
combined
Easiest is to use facets. This requires minor data wrangling (see comments).
suppressMessages(library(tidyverse))
set.seed(42)
foo <- cbind(data.frame(replicate(3, rnorm(30))), date = ISOdate(1,1,1:30))
# make a data frame which has all the values in one column,
# and all the dates in another
# there needs to be a facetting variable
foo %>%
pivot_longer(starts_with("X")) %>%
## combine X1 and X2 to one category
mutate(new_name = ifelse(grepl("X[1-2]", name), "A", "B")) %>%
## now facet by this new variable
ggplot() +
geom_line(aes(date, value, color = name)) +
facet_wrap(~new_name) +
## place at bottom
theme(legend.position = "bottom")
or combining the plots with patchwork
This will require same name and limits of the guides
library(patchwork)
p1 <-
foo %>%
pivot_longer(matches("X[1-2]")) %>%
ggplot() +
geom_line(aes(date, value, color = name)) +
## now define the same names for your color legend and get the same limits
scale_color_brewer("color", limits = paste0("X", 1:3))
p2 <- foo %>%
ggplot() +
geom_line(aes(date, X3, color = "X3")) +
scale_color_brewer("color", limits = paste0("X", 1:3))
p1 + p2 +
## combine the legends
plot_layout(guides = "collect") +
# add tags
plot_annotation(tag_levels = "A") &
## place at bottom
theme(legend.position = "bottom")
Created on 2022-06-29 by the reprex package (v2.0.1)

R method to allow for bar plot with secondary axis with non-overlapping bars

I want to have non-overlapping bars in this plot code. How to achieve that?
library(ggplot2)
p <- ggplot(mtcars) +
geom_bar(aes(x=row.names(mtcars), y=qsec), position = position_dodge(), stat="identity", fill = "red") +
geom_bar(aes(x=row.names(mtcars), y=wt), position = position_dodge(), stat="identity") +
scale_y_continuous(sec.axis = sec_axis(~ .+ max(mtcars$wt), name = "weight")) +
xlab("Name of the car") +
theme(axis.text.x = element_text(angle = 90))
p
You first want to stack the data in the columns that you would like to plot side-by-side. You can do this with pivot_longer().
library(tidyr)
library(ggplot2)
plot_data <- pivot_longer(cbind(model = factor(rownames(mtcars)), mtcars), cols = c("qsec", "wt"))
p <- ggplot(plot_data) +
geom_bar(aes(x=model, y=value, fill = name), position = position_dodge(), stat="identity") +
scale_y_continuous(sec.axis = sec_axis(~ .+ max(mtcars$wt), name = "weight")) +
labs(fill = "Variable",
x = "Name of the car",
y = "qsec",
y2 = "weight") +
theme(axis.text.x = element_text(angle = 90))
p

cowplot: axis title forcefully aligned when aligning two plots

This code replicates the problem:
library(ggplot2)
set.seed(0)
df <- data.frame(ID = letters[1:10],
Var = rnorm(10),
"Some_very_long_label_names" = rnorm(10),
"Not_so_long" = rnorm(10),
"Short" = rnorm(10),
"Incredibly_long_label_name_why_oh_why" = rnorm(10),
"Etc" = rnorm(10))
melted_df <- reshape2::melt(df)
p1 <- ggplot(df, aes(ID, Var)) +
geom_bar(stat = "identity") +
theme(axis.title.x = element_blank())
p2 <- ggplot(melted_df, aes(ID, variable)) +
geom_tile(aes(fill = value)) +
guides(fill = FALSE)
cowplot::plot_grid(p1, p2, nrow = 2, align = "v", axis = "n")
If you run that code, it'll yield this plot:
The problem with this plot lies in the positioning of the y-axis title of the first plot. I thought perhaps setting axis = "n" would stop it from aligning to the axis from the second plot, but it didn't.
My desired output would be this plot, which has aligned the graphics but not the axis labels.
You can use the egg package instead
library(ggplot2)
p1 <- ggplot(df, aes(ID, Var)) +
geom_bar(stat = "identity") +
scale_x_discrete(expand = c(0, 0)) +
theme_bw() +
theme(axis.title.x = element_blank())
p2 <- ggplot(melted_df, aes(ID, variable)) +
geom_tile(aes(fill = value)) +
scale_x_discrete(expand = c(0, 0)) +
theme_bw() +
guides(fill = FALSE)
library(egg)
#> Loading required package: gridExtra
ggarrange(p1, p2, nrow = 2)
Created on 2018-09-21 by the reprex package (v0.2.1.9000)

Add item to legend by theme options

I have a data frame d like this:
d <- data.frame("name" = c("pippo","pluto","paperino"),
"id" = c(1,2,3),"count" = c(10,20,30),
"pvalue"=c(0.01,0.02,0.05),
geneRatio=c(0.5,0.8,0.2),
type=c("KEGG","Reactome","Reactome"))
and I plot a dotplot using the library ggplot:
ggplot(data = d,aes(geneRatio,name,size=count,colour = pvalue)) +
geom_point()+
ggtitle("Significantly Pathways") +
xlab("Gene Ratio") +
ylab("Pathways")+
theme(axis.text.y = element_text(color=d$type))
This is the plot at the moment
I would like to add to legend the information of "type" contained in dataframe d.
I would like to have a new item in the legend with color red = Reactome and color black= KEGG
Not saying that this is a good idea, but you can add a nonsensical geom to force the adding of a guide:
d <- data.frame("name" = c("pippo","pluto","paperino"),
"id" = c(1,2,3),
"count" = c(10,20,30),
"value"=c(0.01,0.02,0.05),
geneRatio=c(0.5,0.8,0.2),
type=c("KEGG","Reactome","Reactome")
)
library(ggplot2)
ggplot(data = d, aes(geneRatio,name,colour = pvalue)) +
geom_point(aes(size=count))+
geom_polygon(aes(geneRatio,name,fill = type)) +
ggtitle("Significantly Pathways") +
xlab("Gene Ratio") +
ylab("Pathways") +
scale_fill_manual(values = c('Reactome'='red', 'KEGG'='black')) +
theme(axis.text.y = element_text(color=d$type))
geom_polygon may not work with your actual data, and you may not find a suitable 'nonsensical' geom. I agree with #zx8754, a facet would be clearer:
ggplot(data = d, aes(geneRatio,name,colour = pvalue)) +
geom_point(aes(size=count)) +
ggtitle("Significantly Pathways") +
xlab("Gene Ratio") +
ylab("Pathways") +
facet_grid(type ~ ., scales = 'free_y', switch = 'y')
You could accomplish this using annotate, but it is a bit manual.
ggplot(data = d, aes(geneRatio, name, size = count, colour = pvalue)) +
geom_point() +
ggtitle("Significantly Pathways") +
xlab("Gene Ratio") +
ylab("Pathways")+
theme(axis.text.y = element_text(color=d$type)) +
annotate("text", x = 0.25, y = 3.5, label = "Reactome", color = "red") +
annotate("text", x = 0.25, y = 3.4, label = "KEGG", color = "black")

alter facet_grid output in ggplot2

This is the current version of my figure:
require(MuMIn)
require(ggplot2)
data(Cement)
d <- data.frame(Cement)
dd <- melt(d,id.var = "y")
ggplot(dd,aes(x = y,y = value, group = variable)) +
geom_point(size = 2) +
theme_classic() +
facet_grid(variable ~ ., scales = "free") +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
xlab("") +
ylab("") +
guides(colour = FALSE)
How can I
1) Alter this graph so that the X1, X2, X3, and X4 labels are on the left hand side and they read c("factor x^2","factor x^3","factor x^4","factor x^5"),
2) Is there a method for surrounding each panel with a box, to make them more distinguishable?
Try this,
library(ggplot2)
library(gtable)
p <- ggplot(mtcars, aes(mpg, cyl))+
facet_grid(gear~., labeller=label_both) + geom_point() +
theme(strip.text.y=element_text(angle=90)) + labs(y="")
g <- ggplotGrob(p)
g$layout[g$layout$name == "strip-right",c("l", "r")] <- 2
grid.newpage()
grid.draw(g)
A solution for question 1 (partial) and 2:
names(d) <- c("x^1","x^2","x^3","x^4","y")
dd <- melt(d,id.var = "y", variable.name="factor")
ggplot(dd, aes(x = y, y = value, group = factor)) +
geom_point(size = 2) +
theme_bw() +
facet_grid(factor ~ ., scales = "free", labeller = label_both) +
theme(axis.text.x = element_text(angle = 90, hjust = 1), panel.grid = element_blank()) +
xlab("") +
ylab("") +
guides(colour = FALSE)
which gives:
Using labeller is a good option (problem #1) and facet_grid and facet_wrap have a switch argument for moving facet labels around a bit (problem #2):
library("ggplot2")
x <- runif(100)
exp <- rep(1:4, each = 25)
y <- x^exp
df <- data.frame(x, y, exp)
# facet_grid
ggplot(df, aes(x, y)) +
facet_grid(exp ~ ., labeller = label_bquote(factor~x^.(exp)), switch = "y") +
geom_point() + labs(y="") +
theme(strip.background = element_blank()) # Remove facet border if you want
# facet_wrap
ggplot(df, aes(x, y)) +
facet_wrap(~ exp, ncol = 1, labeller = label_bquote(factor~x^.(exp)), switch = "y") +
geom_point() + labs(y="") +
theme(strip.background = element_blank())

Resources