Add multiple curves between ggplot2 plots - r

I have two ggplot2 plots and I want to draw a series (10-100) slightly different curves between them. That is, I will have a two-panel layout and want to draw connecting lines from the left plot to the right plot. So far I have tried doing this by converting things to grob's and using the gtable package to add curves.
To illustrate, I have something like:
library(ggplot2)
library(gtable)
library(grid)
library(gridExtra)
p1 = ggplot(data.frame(x=1:10,y=1:10),aes(x=x,y=y))+geom_point()
p2 = ggplot(data.frame(x=1:10,y=1:10),aes(x=x,y=y))+geom_point()
g1 = ggplotGrob(p1)
g2 = ggplotGrob(p2)
gt = gtable:::cbind.gtable(g1,g2,size='first')
gt$heights = unit.pmax(g1$heights,g2$heights)
for(i in 1:10) {
gt = gtable_add_grob(gt,curveGrob(0,0.5,1,0.5,ncp=5,square=FALSE,curvature=i/10),l=5,r=8,b=3,t=3)
}
grid.newpage()
grid.draw(gt)
producing a plot like this:
which is almost right, except only the last of the curveGrob objects is shown. I've tried playing around with the z-index for the added grobs and the last one plotted always overwrites the others. I want my plot to look the same, except it should show all 10 curves between the two plot areas, instead of just the one that is showing with my existing code.
So how can I either modify my existing code to show all 10 curves or achieve the same effect by using a different method? I am stuck using ggplot2 for the main plots, as they are considerably more complex than the toy example shown.

gtable wants unique names for grobs that are in the same position
gt = gtable_add_grob(gt,curveGrob(0,0.5,1,0.5,ncp=5,square=FALSE,curvature=i/10),
l=5,r=8,b=3,t=3, name=paste(i))

Related

Proportion of legend to plot changes when printing two ggplots aligned with grid.arrange to one page (.pdf)

I have a common legend for two ggplot2 graphs which are aligned with grid.arrange() (see code below). However, the legend does not adjust according to graph size, when I export graphs as one pdf.
For a comparison, here is the output of the individual plot:
And after using grid.arrange with the following code:
pdf("Fig1.pdf", onefile=TRUE, paper="a4",width=3.22, height=5)
grid.arrange(Fig1A,Fig1B)
dev.off()
I get this:
The commands for the legend of plot A are:
gglpot2
+theme(legend.key.size=unit(0.5,'lines'))
+theme(legend.key.height=unit(0.25,"cm"))
+theme(legend.key.height=unit(1,"line"))
+theme(legend.text=element_text(size=10))
+theme(legend.position=c(0.85,0.8))
+theme(legend.direction = "vertical")
+guides(fill=guide_legend(title=NULL))
The commands for the legend of plot B are:
+theme(legend.position="")
I tried to solve the issue, according to:
Keep or set the ratio between text labels and size of plot in grid.arrange
which didn’t help, as it is quite similar but not exactly my problem.
https://github.com/baptiste/gridextra/wiki/arranging-ggplot
Here I followed the suggestion:
draw your plots
plot1 <- ggplot(...) # this specifies your first plot
plot2 <- ggplot(...) # this specifies your second plot
plot3 <- ggplot(...) # this specifies your third plot
merge all three plots within one grid (and visualize this)
grid.arrange(plot1, plot2, plot3, nrow=3) #arranges plots within grid
save
g <- arrangeGrob(plot1, plot2, plot3, nrow=3) #generates g
ggsave(file="whatever.pdf", g) #saves g
but I ended up with the same result and worse, as I didn’t have the margins I’d like to have.
https://www.r-bloggers.com/15-questions-all-r-users-have-about-plots/
Printing multiple ggplots into a single pdf, multiple plots per page
didn’t help either, as my problem is not placing the plots on one page, but the ratio of legend size to plot.
Does anyone have a solution?
in the meanwhile I found someone outside this community who was able to help me. The solution is quite simple:
Change the code to
theme(legend.key.size=unit(0.5,'lines'),
legend.key.height=unit(0.32,"cm"),
legend.text=element_text(size=10),
legend.position=c(0.85,0.8),
legend.direction = "vertical")
so basically I removed
theme(legend.key.height=unit(1,"line"))
and
guides(fill=guide_legend(title=NULL))
changed
theme(legend.key.height=unit(0.25,"cm"))
to
theme(legend.key.height=unit(0.32,"cm"))
and that did the job.
I hope this may be usueful for someone else, facing a similar problem.
Best regards!

In R, how can I store an inset graph for later arranging it with grid.arrange?

I have created a graph in which I inset another graph (both ggplot2 objects) via this command:
vp=viewPort(...)
print(ggplotobject1)
print(ggplotobject2, vp=vp)
This works exactly how I'd like it to (one large graph with a custom small graph drawn in the area specified in viewPort).
The problem is that I need to use this combined graph later for arranging it with other plots again through:
grid.arrange(arrangeGrob(..))
Does anyone have an idea how I can store my combined graph as a grob?
Thank you very much indeed!
EDIT:
Responding to baptiste here is a reproducible example:
library(ggplot2)
library(gtable)
library(grid)
data<-mtcars
main_plot<-ggplot(data,aes(hp,mpg,group=cyl))+
geom_smooth(method="lm")+geom_point()+
facet_grid(.~gear)
sub_plot<-ggplot(data,aes(disp,wt,color))+geom_point()
gtable_main<-ggplot_gtable(ggplot_build(main_plot))
gtable_sub<-ggplot_gtable(ggplot_build(sub_plot))
gtable_show_layout(gtable_main)
gtable_main2<-gtable_add_grob(gtable_main,gtable_sub,t=4,l=4,b=1,r=1)
grid.draw(gtable_main2)
This produces the graph I want, but I fail to make the subplot the right size (it's supposed to be a small graph in the bottom left corner of the plot). This is probably really basic, but I haven't worked with gtable before and only a little bit with grid/gridExtra.
Thanks a lot!
you could use annotation_custom or edit the gtable instead of printing to different viewports.
gm <- ggplotGrob(main_plot)
gs <- ggplotGrob(sub_plot)
library(gtable)
library(grid)
panel.id <- 1
panel <- gm$layout[gm$layout$name == "panel",][panel.id,]
inset <- grobTree(gs, vp=viewport(width=unit(1,"in"), x=0.8, y=0.8,
height=unit(1,"in")))
gm <- gtable_add_grob(gm, inset, l=panel$l, t=panel$t)
grid.newpage()
grid.draw(gm)

R heatmap combined with barplot

I am trying to create a heatmap combined with a barplot, such that at the end of every row is a bar with length relevant to that row. The idea is to combine something like the following two into one:
library(gplots)
data(mtcars)
x <- as.matrix(mtcars[,2:11])
hm<-heatmap(x)
barplot(mtcars[hm$rowInd,"mpg"],horiz=T,names.arg=row.names(mtcars)[hm$rowInd],las=2,cex.names=0.7,col="purple",2)
My question is how to combine the two while making the rows and bars align?
Thanks.
You can't combine the plots because (as per the documentation) heatmap() uses layout and draws the image in the lower right corner of a 2x2 layout. Consequentially, it can not be used in a multi column/row layout, i.e., when par(mfrow = *) or (mfcol = *) has been called.
Your best best would be to use ggplot2 and gridExtra to combine the graphs. For this both the heatmap and bar plot need to be created using ggplot.
You can find a heatmap on ggplot2 tutorial here.
Once you have your two plots combine them using the following commands:
#Create the plots
g1 <- heatmap
g2 <- barplot
#Arrange them in a grid
gg1 <- ggplot_gtable(ggplot_build(g1))
gg2 <- ggplot_gtable(ggplot_build(g2))
grid.arrange(gg1, gg2, ncol=2)

positioning plots and table

I would like to plot two histograms and add a table to a pdf file. With the layout function I managed to plot the histograms (plotted them using hist function) where I want them to be but when I used grid.table function from the gridExtra package to add the table the table is laid out on the histograms and I am not able to position them properly. I have tried addtable2plot function but I dont find it visually appealing.
Any thoughts on How do I get around this?
I want my pdf to look like this
histogram1 histogram2
t a b l e
Essentially, one row with two columns and another row with just one column. This is what I did.
require(gridExtra)
layout(matrix(c(1,2,3,3),2,2,byrow=T),heights=c(1,1))
count_table=table(cut(tab$Longest_OHR,breaks=c(0,0.05,0.10,0.15,0.20,0.25,0.30,0.35,0.40,0.45,0.50,0.55,0.60,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1.00)))
ysize=max(count_table)+1000
hist(tab$Longest_OHR,xlab="OHR longest",ylim=c(0,ysize))
count_table=table(cut(tab$Sum_of_OHR.s,breaks=c(0,0.05,0.10,0.15,0.20,0.25,0.30,0.35,0.40,0.45,0.50,0.55,0.60,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1.00)))
ysize=max(count_table)+1000
hist(tab$Sum_of_OHR.s,xlab="OHR Sum",ylim=c(0,ysize))
tmp <- table(cut(tab$Length_of_Gene.Protein, breaks = c(0,100,200,500,1000,2000,5000,10000,1000000000)), cut(tab$Sum_of_OHR.s, breaks = (0:10)/10))
grid.table(tmp)
dev.off()
Any help will be appreciated.
Ram
Here's an example of how to combine two base plots and a grid.table in the same figure.
library(gridExtra)
layout(matrix(c(1,0,2,0), 2))
hist(iris$Sepal.Length, col="lightblue")
hist(iris$Sepal.Width, col="lightblue")
pushViewport(viewport(y=.25,height=.5))
grid.table(head(iris), h.even.alpha=1, h.odd.alpha=1,
v.even.alpha=0.5, v.odd.alpha=1)
The coordinates sent to viewport are the center of the panel. Too see exactly where its boundaries are you can call grid.rect().

Splitting ggplot plot map into 3 frames

Is it possible to extract specific sections of a ggplot figure/map and place them side by side in a secondary figure but still add points to the three frames as if they were still one plot i.e. for the following map
create a map split into 3 sections which can then be manipulated as one graph (i.e. adding points to all three sections of the graph simultaneously?
UPDATE: Reproducible example
set.seed(1)
dfx<-c(sample(1:1000,100),sample(2000:3000,100),sample(4000:3000,100))
dfy<-c(sample(1:1000,100),sample(2000:3000,100),sample(4000:3000,100))
p<-ggplot()+
coord_fixed()+
geom_point(aes(x=dfx,y=dfy))
p
I can get partway there but can't retain the effects of coord_equal or coord_fixed while allowing free scales ... hopefully someone else can step in and get the rest of the way. (This has come up before -- scatterplot with equal axes -- but I haven't seen a solution.)
dd <- data.frame(dfx,dfy)
dd2 <- transform(dd,panel=cut(dfx,seq(0,4000,by=1000),labels=1:4))
p <- ggplot(dd2)+geom_point(aes(dfx,dfy)) + coord_equal()
p + facet_wrap(~panel,nrow=1,scale="free")

Resources