Related
I'm producing a plot_gene_map figure by the genoPlotR R package, which gives a horizontal phylogenetic tree where aligned with each leaf is a genomic segment.
Here's a simple example that illustrates my usage and problem:
The plot_gene_map function requires an ade4s' package phylog object which represents the phylogenetic tree:
tree <- ade4::newick2phylog("(((A:0.08,B:0.075):0.028,(C:0.06,D:0.06):0.05):0.0055,E:0.1);")
A list of genoPlotR's dna_seg objects (which are essentially data.frames with specific columns), where the names of the list elements have to match the names of the leaves of tree:
dna.segs.list <- list(A=genoPlotR::as.dna_seg(data.frame(name=paste0("VERY.LONG.NAME.A.",1:10),start=seq(1,91,10),end=seq(5,95,10),strand=1,col="black",ly=1,lwd=1,pch=1,cex=1,gene_type="blocks",fill="red")),
B=genoPlotR::as.dna_seg(data.frame(name=paste0("VERY.LONG.NAME.B.",1:10),start=seq(1,91,10),end=seq(5,95,10),strand=1,col="black",ly=1,lwd=1,pch=1,cex=1,gene_type="blocks",fill="blue")),
C=genoPlotR::as.dna_seg(data.frame(name=paste0("VERY.LONG.NAME.C.",1:10),start=seq(1,91,10),end=seq(5,95,10),strand=1,col="black",ly=1,lwd=1,pch=1,cex=1,gene_type="blocks",fill="green")),
D=genoPlotR::as.dna_seg(data.frame(name=paste0("VERY.LONG.NAME.D.",1:10),start=seq(1,91,10),end=seq(5,95,10),strand=1,col="black",ly=1,lwd=1,pch=1,cex=1,gene_type="blocks",fill="yellow")),
E=genoPlotR::as.dna_seg(data.frame(name=paste0("VERY.LONG.NAME.E.",1:10),start=seq(1,91,10),end=seq(5,95,10),strand=1,col="black",ly=1,lwd=1,pch=1,cex=1,gene_type="blocks",fill="orange")))
And a list of genoPlotR's annotation objects, which give coordinate information, also named according to the tree leaves:
annotation.list <- lapply(1:5,function(s){
mids <- genoPlotR::middle(dna.segs.list[[s]])
return(genoPlotR::annotation(x1=mids,x2=NA,text=dna.segs.list[[s]]$name,rot=30,col="black"))
})
names(annotation.list) <- names(dna.segs.list)
And the call to the function is:
genoPlotR::plot_gene_map(dna_segs=dna.segs.list,tree=tree,tree_width=2,annotations=annotation.list,annotation_height=1.3,annotation_cex=0.9,scale=F,dna_seg_scale=F)
Which gives:
As you can see the top and right box (gene) names get cut off.
I tried playing with pdf's width and height, when saving the figure to a file, and with the margins through par's mar, but they have no effect.
Any idea how to display this plot without getting the names cut off?
Currently genoPlotR's plot_gene_map does not have a legend option implemented. Any idea how can I add a legend, let's say which shows these colors in squares aside these labels:
data.frame(label = c("A","B","C","D","E"), color = c("red","blue","green","yellow","orange"))
Glad that you like genoPlotR.
There are no real elegant solution to your problem, but here are a few things you can attempt:
- increase annotation_height and reduce annotation_cex
- increase rotation (“rot”) in the annotation function
- use xlims to artificially increase the length of the dna_seg (but that’s a bad hack)
For the rest (including the legend), you’ll have to use grid and its viewports.
A blend of the first 3 solutions:
annotation.list <- lapply(1:5,function(s){
mids <- genoPlotR::middle(dna.segs.list[[s]])
return(genoPlotR::annotation(x1=mids, x2=NA, text=dna.segs.list[[s]]$name,rot=75,col="black"))
})
names(annotation.list) <- names(dna.segs.list)
genoPlotR::plot_gene_map(dna_segs=dna.segs.list,tree=tree,tree_width=2,annotations=annotation.list,annotation_height=5,annotation_cex=0.4,scale=F,dna_seg_scale=F, xlims=rep(list(c(0,110)),5))
For the better solution with grid: (note the "plot_new=FALSE" in the call to plot_gene_map)
# changing rot to 30
annotation.list <- lapply(1:5,function(s){
mids <- genoPlotR::middle(dna.segs.list[[s]])
return(genoPlotR::annotation(x1=mids,x2=NA,text=dna.segs.list[[s]]$name,rot=30,col="black"))
})
names(annotation.list) <- names(dna.segs.list)
# main viewport: two columns, relative widths 1 and 0.3
pushViewport(viewport(layout=grid.layout(1,2, widths=unit(c(1, 0.3), rep("null", 2))), name="overall_vp"))
# viewport with gene_map
pushViewport(viewport(layout.pos.col=1, name="geneMap"))
genoPlotR::plot_gene_map(dna_segs=dna.segs.list,tree=tree,tree_width=2,annotations=annotation.list,annotation_height=3,annotation_cex=0.5,scale=F,dna_seg_scale=F, plot_new=FALSE)
upViewport()
# another viewport for the margin/legend
pushViewport(viewport(layout.pos.col=2, name="legend"))
plotLegend(…)
upViewport()
Hope that helps!
Lionel
Which function or package could I use to add the legend? The R base functions did not seem to work for me. The following message is displayed:
Error in strheight(legend, units = "user", cex = cex) :
plot.new has not been called yet"
I would like to add a global title to a group of subplots using Plots.jl.
Ideally, I'd do something like:
using Plots
pyplot()
plot(rand(10,2), plot_title="Main title", title=["A" "B"], layout=2)
but, as per the Plots.jl documentation, the plot_title attribute is not yet implemented:
Title for the whole plot (not the subplots) (Note: Not currently implemented)
In the meanwhile, is there any way around it?
I'm currently using the pyplot backend, but I'm not especially tied to it.
This is a bit of a hack, but should be agnostic to the backend. Basically create a new plot where the only contents are the title you want, and then add it on top using layout. Here is an example using the GR backend:
# create a transparent scatter plot with an 'annotation' that will become title
y = ones(3)
title = Plots.scatter(y, marker=0,markeralpha=0, annotations=(2, y[2], Plots.text("This is title")),axis=false, grid=false, leg=false,size=(200,100))
# combine the 'title' plot with your real plots
Plots.plot(
title,
Plots.plot(rand(100,4), layout = 4),
layout=grid(2,1,heights=[0.1,0.9])
)
Produces:
More recent versions of Plots.jl support the plot_title attribute, which provides a title for the whole plot. This can be combined with individual titles of individual plots.
using Plots
layout = #layout [a{0.66w} b{0.33w}]
LHS = heatmap(rand(100, 100), title="Title for just the heatmap")
RHS = plot(1:100, 1:100, title="Only the line")
plot(LHS, RHS, plot_title="Overall title of the plot")
Alternatively, you can set the title for an existing plot directly.
p = plot(LHS, RHS)
p[:plot_title] = "Overall title of the plot"
plot(p)
When using the pyplot backend, you can use PyPlot commands to alter a Plots figure, cf. Accessing backend specific functionality with Julia Plots.
To set a title for the whole figure, you could do something like:
using Plots
p1 = plot(sin, title = "sin")
p2 = plot(cos, title = "cos")
p = plot(p1, p2, top_margin=1cm)
import PyPlot
PyPlot.suptitle("Trigonometric functions")
PyPlot.savefig("suptile_test.png")
One needs to explicitly call PyPlot.savefig to see the effect of the PyPlot functions.
Note that all changes made using the PyPlot interface will be overwritten when you use a Plots function.
subplots are fields of the Plot type, and each subplot has a field called :attr that you can modify and re-display() the plot. Try the following:
julia> l = #layout([a{0.1h} ;b [c; d e]])
Plots.GridLayout(2,1)
julia> p = plot(randn(100,5),layout=l,t=[:line :histogram :scatter :steppre :bar],leg=false,ticks=nothing,border=false)
julia> p.subplots
5-element Array{Plots.Subplot,1}:
Subplot{1}
Subplot{2}
Subplot{3}
Subplot{4}
Subplot{5}
julia> fieldnames(p.subplots[1])
8-element Array{Symbol,1}:
:parent
:series_list
:minpad
:bbox
:plotarea
:attr
:o
:plt
julia> for i in 1:length(p.subplots)
p.subplots[i].attr[:title] = "subtitle $i"
end
julia> display(p)
You should now see a title in each subplot
I'm trying to use a trellis theme to set all my graphing parameters to keep my plotting statements short. I can't seem to find the correct trellis parameter access tick mark length (or any scale parameters for that matter).
library(lattice)
x = runif(100)
my.theme = trellis.par.get()
my.theme$axis.line = list(tck=c(4)) # this does not work
dp <- densityplot(~x)
# this works, but I want to do it using a theme
# dp <-densityplot(~x, scales=list(y=list(tck=c(4))))
png("dp.png", width=400, height=200)
trellis.par.set(my.theme)
plot(dp); dev.off()
Tick lengths for each of the plot's axes are controlled by (elements of) axis.components in lattice's graphical parameter list.
Run str(trellis.par.get("axis.components")) to see what you are aiming for, and then do something like the following:
mytheme <- list(axis.components = list(left = list(tck=4), right = list(tck=4)))
trellis.par.set(mytheme)
densityplot(~x)
I would like to add LaTeX typesetting to elements of plots in R (e.g: the title, axis labels, annotations, etc.) using either the combination of base/lattice or with ggplot2.
Questions:
Is there a way to get LaTeX into plots using these packages, and if so, how is it done?
If not, are there additional packages needed to accomplish this.
For example, in Python matplotlib compiles LaTeX via the text.usetex packages as discussed here: http://www.scipy.org/Cookbook/Matplotlib/UsingTex
Is there a similar process by which such plots can be generated in R?
The CRAN package latex2exp contains a TeX function that translate LaTeX formulas to R's plotmath expressions. You can use it anywhere you could enter mathematical annotations, such as axis labels, legend labels, and general text.
For example:
x <- seq(0, 4, length.out=100)
alpha <- 1:5
plot(x, xlim=c(0, 4), ylim=c(0, 10),
xlab='x', ylab=TeX(r'($\alpha x^\alpha$, where $\alpha \in \{1 \ldots 5\}$)'),
type='n', main=TeX(r'(Using $\LaTeX$ for plotting in base graphics!)', bold=TRUE))
for (a in alpha) {
lines(x, a*x^a, col=a)
}
legend('topleft',
legend=TeX(sprintf(r'($\alpha = %d$)', alpha)),
lwd=1,
col=alpha)
produces this plot.
Here's an example using ggplot2:
q <- qplot(cty, hwy, data = mpg, colour = displ)
q + xlab(expression(beta +frac(miles, gallon)))
As stolen from here, the following command correctly uses LaTeX to draw the title:
plot(1, main=expression(beta[1]))
See ?plotmath for more details.
You can generate tikz code from R:
http://r-forge.r-project.org/projects/tikzdevice/
Here's something from my own Lab Reports.
tickzDevice exports tikz images for LaTeX
Note, that in certain cases "\\" becomes "\" and "$" becomes "$\" as in the following R code: "$z\\frac{a}{b}$" -> "$\z\frac{a}{b}$\"
Also xtable exports tables to latex code
The code:
library(reshape2)
library(plyr)
library(ggplot2)
library(systemfit)
library(xtable)
require(graphics)
require(tikzDevice)
setwd("~/DataFolder/")
Lab5p9 <- read.csv (file="~/DataFolder/Lab5part9.csv", comment.char="#")
AR <- subset(Lab5p9,Region == "Forward.Active")
# make sure the data names aren't already in latex format, it interferes with the ggplot ~ # tikzDecice combo
colnames(AR) <- c("$V_{BB}[V]$", "$V_{RB}[V]$" , "$V_{RC}[V]$" , "$I_B[\\mu A]$" , "IC" , "$V_{BE}[V]$" , "$V_{CE}[V]$" , "beta" , "$I_E[mA]$")
# make sure the working directory is where you want your tikz file to go
setwd("~/TexImageFolder/")
# export plot as a .tex file in the tikz format
tikz('betaplot.tex', width = 6,height = 3.5,pointsize = 12) #define plot name size and font size
#define plot margin widths
par(mar=c(3,5,3,5)) # The syntax is mar=c(bottom, left, top, right).
ggplot(AR, aes(x=IC, y=beta)) + # define data set
geom_point(colour="#000000",size=1.5) + # use points
geom_smooth(method=loess,span=2) + # use smooth
theme_bw() + # no grey background
xlab("$I_C[mA]$") + # x axis label in latex format
ylab ("$\\beta$") + # y axis label in latex format
theme(axis.title.y=element_text(angle=0)) + # rotate y axis label
theme(axis.title.x=element_text(vjust=-0.5)) + # adjust x axis label down
theme(axis.title.y=element_text(hjust=-0.5)) + # adjust y axis lable left
theme(panel.grid.major=element_line(colour="grey80", size=0.5)) +# major grid color
theme(panel.grid.minor=element_line(colour="grey95", size=0.4)) +# minor grid color
scale_x_continuous(minor_breaks=seq(0,9.5,by=0.5)) +# adjust x minor grid spacing
scale_y_continuous(minor_breaks=seq(170,185,by=0.5)) + # adjust y minor grid spacing
theme(panel.border=element_rect(colour="black",size=.75))# border color and size
dev.off() # export file and exit tikzDevice function
Here's a cool function that lets you use the plotmath functionality, but with the expressions stored as objects of the character mode. This lets you manipulate them programmatically using paste or regular expression functions. I don't use ggplot, but it should work there as well:
express <- function(char.expressions){
return(parse(text=paste(char.expressions,collapse=";")))
}
par(mar=c(6,6,1,1))
plot(0,0,xlim=sym(),ylim=sym(),xaxt="n",yaxt="n",mgp=c(4,0.2,0),
xlab="axis(1,(-9:9)/10,tick.labels,las=2,cex.axis=0.8)",
ylab="axis(2,(-9:9)/10,express(tick.labels),las=1,cex.axis=0.8)")
tick.labels <- paste("x >=",(-9:9)/10)
# this is what you get if you just use tick.labels the regular way:
axis(1,(-9:9)/10,tick.labels,las=2,cex.axis=0.8)
# but if you express() them... voila!
axis(2,(-9:9)/10,express(tick.labels),las=1,cex.axis=0.8)
I did this a few years ago by outputting to a .fig format instead of directly to a .pdf; you write the titles including the latex code and use fig2ps or fig2pdf to create the final graphic file. The setup I had to do this broke with R 2.5; if I had to do it again I'd look into tikz instead, but am including this here anyway as another potential option.
My notes on how I did it using Sweave are here: http://www.stat.umn.edu/~arendahl/computing
I just have a workaround. One may first generate an eps file, then convert it back to pgf using the tool eps2pgf. See http://www.texample.net/tikz/examples/eps2pgf/
h <- rnorm(mean = 5, sd = 1, n = 1000)
hist(h, main = expression(paste("Sampled values, ", mu, "=5, ", sigma,
"=1")))
Taken from a very help article here https://stats.idre.ucla.edu/r/codefragments/greek_letters/
You can use the following, for example:
title(sub=TeX(sprintf(paste("Some latex symbols are ", r'(\lambda)', "and", r'(\alpha)'))))
Just remember to enclose LaTeX expressions in paste() using r'()'
You can also add named objects in the paste() function. E.g.,
lambda_variable <- 3
title(sub=TeX(sprintf(paste(r'(\lambda=)', lambda_variable))))
Not sure if there are better ways to do this, but the above worked for me :)
I would like to place two (somewhat non-standard) grid graphics in a single plot in R.
Try:
require(vcd)
mosaic(Titanic)
assoc(Titanic)
The trouble is that these aren't lattice graphics, and to my knowledge do not come with a layout argument or similar. And since these are grid graphs, they're impervious to base graph tricks like par(mfrow=c(1,2)).
How can I place the two graphs above in a single plot, with both graphs on the same line?
I already tried the suggestions in How to plot grid plots on a same page?, but they don't seem to work for vcd plots. Ultimately I would like to obtain something similar to:
Neither plot seems to return any object and I cant see how to grab the grobs from looking at grid.ls(). So using the idea from this answer
library(vcd)
library(gridGraphics)
library(gridExtra)
mosaic(Titanic)
m <- grid.grab()
assoc(Titanic)
a <- grid.grab()
grid.newpage()
grid.arrange(m, a, ncol=2)
Im sure there will be a more grid-like approach but ...
Something similar to the solution in How to plot grid plots on a same page? can also be used for vcd displays. The difference is that you need to set newpage = FALSE (to prevent opening a new display) and you need to push and pop the viewport yourself (which can be handy when re-using vcd graphics in more complicated displays such as partykit trees).
The mosaic and association display for the Titanic data can be visualized as:
grid.newpage()
pushViewport(viewport(layout = grid.layout(1, 2)))
pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1))
mosaic(Titanic, newpage = FALSE)
popViewport()
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2))
assoc(Titanic, newpage = FALSE)
popViewport()
yielding
Another option is vcd’s mplot() function (for details, see ?vcd::mplot):
library(vcd)
mplot(
mosaic(Titanic, return_grob = TRUE),
assoc(Titanic, return_grob = TRUE),
keep_aspect_ratio = FALSE
)