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)
Related
I am trying to plot my two figures on the same page in R.
Two plots are: Scatter and bat plot
Used: par(mfrow=c(2,1))
p
s
where p is the bar plot and s is the scatter plot.
When I used the command: first p plot shows and at the end only s-- scatter plot is shown.
I know both the plots are there but could not fix it!!
I really need a help here.
There is small problem in code provided by OP. The wrong dataframe is used in scatter plot.
The correct implementation could be:
#The dataset read is has been modified to read from text as provided in OP
dataset <- read.table(text = "Category Jan Feb
Food 25 100
Makeup 10 150
Travel 200 120
Drinks 164 36", header = TRUE, stringsAsFactors = FALSE)
# mfrow setting will not have any effect on ggplot2 based
par(mfrow=c(2,1))
p<-ggplot(dataset, aes(x=Category, y=Jan)) + geom_bar(stat="identity",)
# OP has used just data for ggplot function to s
s<-ggplot(dataset, aes(x=Category, y=Feb)) + geom_point()
p
s
But the graphs will be drawn in separate pages.
grid.arrange() function gridExtra can be used to draw multiple ggplot based plots in same screen.
You can use multi-graph function and plot any number of graphs on the same page.
Examples below:
http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/
Note: it's a custom function, so it's not in any packages. You should just copy and paste, then run it in your console.
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))
I've been learning ggplot2, and hope to use it for all my R graphing. However, I've yet to find a way to make a contour plot that looks analogous to a conventional contour plot, like what can be obtained using lattice:filled.contour(). For example:
#define data
x<-seq(1,11,1)
y<-seq(1,11,1)
xyz.func<-function(x,y) {-10.4+6.53*x+6.53*y-0.167*x^2-0.167*y^2+0.0500*x*y}
#contour plot using lattice graphics and R Color Brewer
library(lattice) #for filled.contour()
library(RColorBrewer) #for brewer.pal()
z.lattice<-outer(x,y,xyz.func)
filled.contour(x,y,z.lattice,nlevels=6,col=brewer.pal(6,"YlOrRd"))
This gives me a nice contour plot.
Now, let's try the same thing in ggplot2. The best I can come up with, based on everything I've read (particularly Drawing labels on flat section of contour lines in ggplot2) is:
#contour plot using ggplot2
library(ggplot2)
library(reshape2) #for melt()
z.molten<-melt(z.lattice)
names(z.molten) <- c("x", "y", "z")
v<-ggplot(z.molten, aes(x,y,z=z))+
geom_tile(aes(fill=z))+
stat_contour(bins=6,aes(x,y,z=z), color="black", size=0.6)+
scale_fill_gradientn(colours=brewer.pal(6,"YlOrRd"))
v
This graph has the same basic idea as filled.contour(), but the colored tiles don't conform to the contours very well.
I haven't been successful with changing the sizes of the tiles, either.
Any suggestions on how to make ggplot2's output closer to filled.contour()'s output?
The essence of your question, it seems, is how to produce a contour plot in ggplot with discrete filled contours, rather than continuous contours as you would get using the conventional geom_tile(...) approach. Here is one way.
x<-seq(1,11,.03) # note finer grid
y<-seq(1,11,.03)
xyz.func<-function(x,y) {-10.4+6.53*x+6.53*y-0.167*x^2-0.167*y^2+0.0500*x*y}
gg <- expand.grid(x=x,y=y)
gg$z <- with(gg,xyz.func(x,y)) # need long format for ggplot
library(ggplot2)
library(RColorBrewer) #for brewer.pal()
brks <- cut(gg$z,breaks=seq(0,100,len=6))
brks <- gsub(","," - ",brks,fixed=TRUE)
gg$brks <- gsub("\\(|\\]","",brks) # reformat guide labels
ggplot(gg,aes(x,y)) +
geom_tile(aes(fill=brks))+
scale_fill_manual("Z",values=brewer.pal(6,"YlOrRd"))+
scale_x_continuous(expand=c(0,0))+
scale_y_continuous(expand=c(0,0))+
coord_fixed()
The use of, e.g., scale_x_continuos(...) is just to get rid of the extra space ggplot puts around the axis limits; fine for most things but distracting in contour plots. The use of coord_fixed(...) is just to set the aspect ratio to 1:1. These are optional.
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().
I'm trying to inset a plot using ggplot2 and annotation_custom (the plot is actually a map that I'm using to replace the legend). However, I'm also using facet_wrap to generate multiple panels, but when used with annotation_custom, this reproduces the plot in each facet. Is there an easy way to insert the plot only once, preferably outside the plotting area?
Here is a brief example:
#Generate fake data
set.seed(9)
df=data.frame(x=rnorm(100),y=rnorm(100),facets=rep(letters[1:2]),
colors=rep(c("red","blue"),each=50))
#Create base plot
p=ggplot(df,aes(x,y,col=colors))+geom_point()+facet_wrap(~facets)
#Create plot to replace legend
legend.plot=ggplotGrob(
ggplot(data=data.frame(colors=c("red","blue"),x=c(1,1),y=c(1,2)),
aes(x,y,shape=colors,col=colors))+geom_point(size=16)+
theme(legend.position="none") )
#Insert plot using annotation_custom
p+annotation_custom(legend.plot)+theme(legend.position="none")
#this puts plot on each facet!
This produces the following plot:
When I would like something more along the lines of:
Any help is appreciated. Thanks!
In the help of annotation_custom() it is said that annotations "are the same in every panel", so it is expected result to have your legend.plot in each facet (panel).
One solution is to add theme(legend.position="none") to your base plot and then use grid.arrange() (library gridExtra) to plot both plots.
library(gridExtra)
p=ggplot(df,aes(x,y,col=colors))+geom_point()+facet_wrap(~facets)+
theme(legend.position="none")
grid.arrange(p,legend.plot,ncol=2,widths=c(3/4,1/4))