Combining ggplots in R with common legend - r

I have 4 graphs that are similar to this one (just use a different dataframe (don, don1, don2). I want to combine them in one graph with the line colors designated as the dataframe with a common legend.
ggplot(don, aes(x=poscum, y=pval)) +
# Show all points
geom_line() +
# custom X axis:
scale_x_continuous( label = axisdf$CHR, breaks= axisdf$center ) +
scale_y_continuous(expand = c(0, 0) ) + # remove space between plot area
and x axis
# Custom the theme:
theme_bw() +
theme(
legend.position="none",
panel.border = element_blank(),
panel.grid.major = element_line(colour="white"),
panel.grid.minor = element_line(colour="white"),
axis.ticks = element_line(colour = "black"),
axis.line = element_line(colour = "black"),
)

You can use facets for this. Like so:
donall <- data.frame(rbind(don, don1, don2), group= rep("don", nrow(don)), rep("don1", nrow(don1)), rep("don2", nrow(don2)))
ggplot(donall, aes(x=poscum, y=pval)) +
geom_line()+
facet_wrap(~group, ncol=2) +....

Related

Barplot with both stacked and grouped options, without face grid

I am trying to make a stacked and grouped barplot using the following datasets:
dfplot <- data.frame(organisms=c("M.musculus","D.melanogaster" ,"H.sapiens","O.sativa","S.pombe","C.familiaris",
"G.gallus","P.falciparum","A.thaliana","C.elegans","D.rerio","B.taurus","S.cerevisiae","R.norvegicus","C.intestinalis","B.subtilis","E.coli"),
KEGGv2=c(20,7,21,126,106,62,26,80,5,5,13,306,8,35,32,104,107),
KEGGv1=c(286,124,289,0,0,244,135,0,121,124,148,0,101,271,87,0,0),
Reactome=c(358,146,596,115,54,306,370,23,155,112,365,341,52,364,0,0,0))
# Melt the dataframe
melted <- melt(dfplot, "organisms")
# Reformat the data labels
melted$cat <- ''
melted[melted$variable == 'Reactome',]$cat <- "Reactome"
melted[melted$variable != 'Reactome',]$cat <- "KEGG"
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~ organisms)+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
strip.text.x = element_blank(),
strip.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"))
And my output is the following one:
I used a facet_grid per organism because I wanted to have a mix between stack (for both KEGGv1 and KEGGv2) and then group it with the other group Reactome. However, when doing the melting, the x-axis will have two labels per facet_grid (KEGG and Reactome, which is the variable obtained from the melting [cat]). I did not want that label so I remove them.
What I am trying to do is to have the organism name per each of the groupings, so each of the 17 grouping bars will have the name of the corresponding organism**. Therefore, I am missing that, I have tried several ways but I cannot find the proper way of doing it.
Thanks in advance,
You can do two things to make this work:
Rotate the labels of the facet so that they plot at 90 degrees
Plot the facet labels beneath the graph using the switch = 'x' argument within facet_grid.
Here is the complete example:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~organisms, switch = 'x')+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.y = element_line(colour = "black"),
strip.text = element_text(angle = 90))
I left the default shaded background, but you can easily style as you prefer.
Aproach Two
You might want to consider rotating the plot. This requires you to flip the coordinates of the plot using coord_flip before the facet is called. As we are faceting in the other direction we change the facet argument to facet_grid(organisms~.). All other arguments which refer to x or y are swapped over:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
coord_flip() +
facet_grid(organisms~., switch = 'y') +
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.x = element_line(colour = "black"),
strip.text.y = element_text(angle = 180))
First you can set the organism labels to be below the bars, rather than above. This is established by setting the switch argument of the facet_grid function to "x" (see code below). Secondly, you should then remove axis.title.x=element_blank() argument within your theme function call. The updated code is below. Hope this helps!
ggplot(melted, aes(x = cat, y = value, fill =variable)) +
geom_bar(stat = 'identity', position = 'stack') +facet_grid(~organisms, switch="x")+
scale_fill_manual(values=c("deepskyblue4","lightblue1","olivedrab2"))+
ylab("Number of pathways")+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank())+theme(legend.title=element_blank())+
theme(strip.background = element_blank())+theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),panel.background = element_blank(), axis.line = element_line(colour = "black"))

Can you get the axis of the marginal densities to line up with the axis of the scatter plot

Hi I have the plot below and the marginal density plots are slightly off. They do not line up to the x and y axis of the scatter plot so interpretation can be a bit misleading.
I can sort of play with these lines of code to try and get the margins to align for rthe marginal plots but it is very manual and frustrating.
theme0(plot.margin = unit(c(1,0,0,2.2),"lines"))
theme0(plot.margin = unit(c(0,1,1.2,0),"lines"))
Is there a way to automatically find the right margins to pass to theme0(plot.margin = unit(c(0,1,1.2,0),"lines") so that no manual work needs to be done to line up the margins? Thank you.
library(ggplot2)
library(gridExtra)
set.seed(42)
DF <- data.frame(x=rnorm(100,mean=c(1,5)),y=rlnorm(100,meanlog=c(8,6)),group=1:2)
DF
## Scatter plot
p1 <- ggplot(DF,aes(x=x,y=y)) + geom_point() +
scale_x_continuous(expand=c(0.02,0)) +
scale_y_continuous(expand=c(0.02,0)) +
theme_bw() +
theme(legend.position="none",plot.margin=unit(c(0,0,0,0),"points")) # ggplot(DF,aes(x=x,y=y,colour=factor(group))) color the gorup
theme0 <- function(...) theme( legend.position = "none",
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.margin = unit(0,"null"),
axis.ticks = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.ticks.length = unit(0,"null"),
axis.ticks.margin = unit(0,"null"),
panel.border=element_rect(color=NA),...)
### DENSITY OF X
p2 <- ggplot(DF,aes(x=x, fill="blue")) +
geom_density(alpha=0.5) +
scale_x_continuous(breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(1,0,0,2.2),"lines")) # to color group ggplot(DF,aes(x=x,colour=factor(group),fill=factor(group)))
### DENSITY OF Y
p3 <- ggplot(DF,aes(x=y, fill = "red")) +
geom_density(alpha=0.5) +
coord_flip() +
scale_x_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(0,1,1.2,0),"lines")) # color group ggplot(DF,aes(x=y,colour=factor(group),fill=factor(group)))
grid.arrange(arrangeGrob(p2,ncol=2,widths=c(3,1)),
arrangeGrob(p1,p3,ncol=2,widths=c(3,1)),
heights=c(1,3))

Use distance between y-axis ticks as variable in ggplot2

Is there a way to use the distance between the ticks in the y-axis as variable within ggplot function?
I want to plot an annotation whose y-coordinate can be "responsive" to the y-axis scale of a graph.
In the example below, I would like var1 to be the distance between successive y-axis ticks as taken from the parameters of the specific graph, and not a user-defined constant.
Data:
EXse2<- data.frame(wk=c(1,2), EX=c(4.457143, 2.580952), se=c(0.4209481,0.5519333))
Code:
var1<- 0.1
labEX<- "\u002A\u002A"
library(ggplot2)
ggplot(EXse2, aes(x=factor(wk), y=EX, group=1))+
geom_errorbar(aes(ymin=EX-se, ymax=EX+se), width=.2, size=1)+
geom_line(size=1)+
geom_point(size=2)+
annotate("text", label=labEX, x=1.5, y=(mean(EXse2$EX[1:2])+var1))+
xlab("period")+
ylab(expression(bar(EX)))+
theme(
panel.background=element_blank(),
panel.border = element_blank(),
panel.grid.minor.x=element_blank(),
panel.grid.major.x=element_blank(),
panel.grid.minor.y = element_line(colour = "#d9d9d9"),
panel.grid.major.y = element_line(colour = "#bfbfbf"),
axis.line = element_line()
)
You can achieve this by creating to plot first, extracting the tick distances with ggplot_build and then add the annotation:
library(ggplot2)
EXse2<- data.frame(wk=c(1,2), EX=c(4.457143, 2.580952), se=c(0.4209481,0.5519333))
labEX<- "\u002A\u002A"
#first, put your plot in p1
p1 <-
ggplot(EXse2, aes(x=factor(wk), y=EX, group=1))+
geom_errorbar(aes(ymin=EX-se, ymax=EX+se), width=.2, size=1)+
geom_line(size=1)+
geom_point(size=2)+
# I HAVE REMOVED THE ANNOTATE HERE
xlab("period")+
ylab(expression(bar(EX)))+
theme(
panel.background=element_blank(),
panel.border = element_blank(),
panel.grid.minor.x=element_blank(),
panel.grid.major.x=element_blank(),
panel.grid.minor.y = element_line(colour = "#d9d9d9"),
panel.grid.major.y = element_line(colour = "#bfbfbf"),
axis.line = element_line()
)
# extract axis limits
yminticks <- ggplot_build(p1)$panel$ranges[[1]]$y.minor_source
# subtract first tick from second
var1 <- yminticks[2] - yminticks[1]
# and now add the annotate and plot
p1 +
annotate("text", label=labEX, x=1.5, y=(mean(EXse2$EX[1:2])+var1))

ggplot2: modify legend's elements for two factors in scatterplot {ggplot2}?

I wish my scatter plot displays two factors: by point size and by shades of grey:
a1<-c(seq(1,10,1))
a2<-c(seq(11,20,1))
a3<-c(rep(c(1,2),each = 5))
a4<-c(rep(c(5,10,15,20,25),2))
df<-data.frame(a1,a2,a3,a4)
t1<-theme(
plot.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.line = element_line(size=.4))
ggplot(df, aes(x= a1, y= a2)) +
geom_point(aes(alpha=factor(a3), size = factor(a4))) + t1 + labs(x = "x label", y = "y label") +
theme(legend.background = element_rect())
So far, more or less good.
My questions are:
how to remove the background in my legend? theme(legend.background = element_rect()) for some reason doesn't work...
how to modify both my legends headers? I imagine by this example : http://www.cookbook-r.com/Graphs/Legends_(ggplot2)/
that is should be something like:
scale_shape_discrete(name ="modified A4", breaks=c("1", "2"), labels = c("one","two")) but I can't figure that how to make it work?
I am sure that I am completely misunderstanding the displaying of two variables in scatter plot, but I can't find a way how to correct it?
Thank you !
Based on suggestions of #user20650 and #inscaven and on more google search I hope to understand better how the ggplot is organized and how to produce my plot:
# dummy data
a1<-c(seq(1,10,1))
a2<-c(seq(11,20,1))
a3<-c(rep(c(1,2),each = 5))
a4<-c(rep(c(5,10,15,20,25),2))
# create data frame
df<-data.frame(a1,a2,a3,a4)
# set nice theme
t1<-theme(
plot.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.line = element_line(size=.4))
# create scatter plot
ggplot(df, aes(x= a1, y= a2)) + # create basic plot
geom_point(aes(size = factor(a4), colour = factor(a3))) + # colour has to be inside of aes !! (ASSIGNED = MAPPED)
scale_colour_grey(name = "Set second\nline in title") + # change title of 1st legend, change colours
scale_size_discrete(name = "Name by size") + # change title of 2nd legend, size of point has been already assigned
theme(legend.key = element_blank()) + # delete grey boxes around the legend
labs(x = "x label", y = "y label") + # set labels on x and y axes
t1 # add nice theme
which results in:

Disable y axis scale and labels

I have a plot in ggplot:
ggplot(plot1,aes(x=c,y=value,colour=variable,linetype=variable,size=variable)) +
geom_line() +
scale_x_continuous(breaks=seq(1,10,1)) +
scale_y_continuous(breaks=seq(0,1, 0.1))+
scale_colour_manual(values=rep(c("blue3","red3"),each=9)) +
scale_linetype_manual(values = rep(c(3,1),each=9)) +
scale_size_manual(values = rep(c(0.6,0.3),each=9)) +
theme_bw(base_size=12, base_family="Helvetica") +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=8),
text = element_text(size=14),
axis.line = element_line(size=0.25),
axis.ticks=element_line(size=0.25),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
legend.position="none" ,
legend.direction="vertical",
legend.title=element_blank(),
legend.text=element_text(size=8),
legend.background=element_blank(),
legend.key=element_blank())+labs(title='a',x='b', y='c' )+theme(plot.title=element_text(size=8))+theme(plot.margin=unit(c(0.1,0,0.1,0),"cm"))
I would like to disable:
the numbers on the y axis
the small lines indicating the position of the numbers
the label
Is this possible to do without affecting the x axis?
I think you can use this approach.
p1 + theme(axis.text.y=element_blank())+ylab("") + scale_y_discrete(breaks=NULL)
# p1 = your initial graph
# axis.text.y removes number
# ylab("") removes y label
# scale_y_discrete(breaks=NULL) removes the tick marks. Your x-axis will not be affected.
Good luck.
You can also do everything in the theme() part of your code. Just add the following code:
p1 + theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())

Resources