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)
Related
I plotted a DotPlot following these incredible steps (https://davemcg.github.io/post/lets-plot-scrna-dotplots/) from David but I could only reach the DotPlot part. I tried to calculate and plot the dendrogram and reorder my data, but I didn't succeed.
My code:
> teste2 %>% filter(bacteria %in% markers) %>%
+ ggplot(aes(x = bacteriophage, y = bacteria, color = eop_index, size = virulence_index)) +
+ geom_point() +
+ scale_color_viridis_c(name = 'EOP') +
+ cowplot::theme_cowplot() +
+ theme(axis.line = element_blank()) +
+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
+ ylab('') +
+ xlab('') +
+ theme(axis.ticks = element_blank())
My result: DotPlot
What I need:
DotPlot that I based my results
It's important to say that the type of data is different. I'm not working with scRNA data, so I'm adapting to my needs. When I apply the same code of David but change the variable names, the result is completely nonsense and does not reorder the data.
The code:
> mat <- teste2 %>%
+ filter(bacteria %in% markers) %>%
+ pivot_wider(names_from = bacteriophage, values_from = eop_index) %>%
+ data.frame() # make df as tibbles -> matrix annoying
> mat <- mat[,-1] #drop gene column as now in rows
> clust <- hclust(dist(mat %>% as.matrix())) # hclust with distance matrix
> ddgram <- as.dendrogram(clust) # create dendrogram
> ggtree_plot <- ggtree::ggtree(ddgram)
> ggtree_plot
> dotplot <- teste2 %>% filter(bacteria %in% markers) %>%
+ mutate(bacteria, factor(bacteria, levels = clust$labels[clust$order])) %>%
+ ggplot(aes(x = bacteriophage, y = bacteria, color = eop_index, size = virulence_index)) +
+ geom_point() +
+ scale_color_viridis_c(name = 'EOP') +
+ cowplot::theme_cowplot() +
+ theme(axis.line = element_blank()) +
+ theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
+ ylab('') +
+ xlab('') +
+ theme(axis.ticks = element_blank())
> plot_grid(ggtree_plot, dotplot, nrow = 1, rel_widths = c(0.5,2), align = 'h')
The result: DotPlot with dendrogram rsrs
Here is a sample of my data: Screenshot of data
If someone could help me, I would appreciate it very much!
Thanks in advance!
Obs: I tried to change the variables at different ways, but any of them result a correct dendrogram and reorder the dotplot data sequence.
I created a ggplot graph using ggsegment for certain subcategories and their cost.
df <- data.frame(category = c("A","A","A","A","A","A","B","B","B","B","B","B","B"),
subcat = c("S1","S2","S3","S4","S5","S6","S7","S8","S9","S10","S11","S12","S13"),
value = c(100,200,300,400,500,600,700,800,900,1000,1100,1200,1300))
df2 <- df %>%
arrange(desc(value)) %>%
mutate(subcat=factor(subcat, levels = subcat)) %>%
ggplot(aes(x=subcat, y=value)) +
geom_segment(aes(xend=subcat, yend=0)) +
geom_point(size=4, color="steelblue") +
geom_text(data=df, aes(x=subcat, y=value, label = dollar(value, accuracy = 1)), position = position_nudge(x = -0.3), hjust = "inward") +
theme_classic() +
coord_flip() +
scale_y_continuous(labels = scales::dollar_format()) +
ylab("Cost Value") +
xlab("subcategory")
df2
This code results in a graph that is shown below:
My main issue is I want the category variable on the left of the subcategory variables. It should look like this:
How do I add the category variables in the y-axis, such that it looks nested?
As mentioned in my comment and adapting this post by #AllanCameron to your case one option to achieve your desired result would be the "facet trick", which uses faceting to get the nesting and some styling to remove the facet look:
Facet by category and free the scales and the space so that the distance between categories is the same.
Remove the spacing between panels and place the strip text outside of the axis text.
Additionally, set the expansion of the discrete x scale to .5 to ensure that the distance between categories is the same at the facet boundaries as inside the facets.
library(dplyr)
library(ggplot2)
library(scales)
df1 <- df %>%
arrange(desc(value)) %>%
mutate(subcat=factor(subcat, levels = subcat))
ggplot(df1, aes(x=subcat, y=value)) +
geom_segment(aes(xend=subcat, yend=0)) +
geom_point(size=4, color="steelblue") +
geom_text(data=df, aes(x=subcat, y=value, label = dollar(value, accuracy = 1)), position = position_nudge(x = -0.3), hjust = "inward") +
theme_classic() +
coord_flip() +
scale_y_continuous(labels = scales::dollar_format()) +
scale_x_discrete(expand = c(0, .5)) +
facet_grid(category~., scales = "free_y", switch = "y", space = "free_y") +
ylab("Cost Value") +
xlab("subcategory") +
theme(panel.spacing.y = unit(0, "pt"), strip.placement = "outside")
I currently have this plot:
current plot without mean line
I want to add a continuous line in the plot that shows the mean value of each x-axis point.
How can i do this? Here is my code:
data <- ndpdata[which(ndpdata$FC.Fill.Size==250),] #250 fill size
data$PS_DATE <- as.Date(data$PS_DATE, "%Y-%m-%d")
data$PS_DATE <- as.Date(data$PS_DATE, "%m-%d-%Y")
data$final <- paste(data$PS_DATE, data$FC.Batch.Nbr, sep=" ") %>% na.omit()
library(tidyr)
my_df_long <- gather(data, group, y, -final)
data = my_df_long[2075:2550,] %>% na.omit()
ggplot(data, aes(final, y, color=final), na.rm=TRUE) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + theme(legend.position = "none") + geom_point(na.rm=TRUE) +
scale_y_discrete(breaks = c(251,270,290,310,325))
First, for the future please note the note of MrFlick.
We could use stat_summary. x should be factor and in a meaningful order.
I can't test because no data provided:
ggplot(data, aes(x=factor(final), y, color=final), na.rm=TRUE) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) + theme(legend.position = "none") + geom_point(na.rm=TRUE) +
scale_y_discrete(breaks = c(251,270,290,310,325)) +
stat_summary(fun=mean, colour="red", geom="line", aes(group = 1))
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.
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)