Adding global title to Plots.jl subplots - julia

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

Related

Move title of plots in a list of plots in R

I have a list of plots that I have assigned names to, and then converted to plot titles as suggested by https://stackoverflow.com/a/14790376/9335733. The titles happen to appear over the top x-axis title and so I attempt to move them as suggested here: https://stackoverflow.com/a/44618277/9335733. The overall code looks as follows:
lapply(names(Cast.files), function (x) plot(Cast.files[[x]],
main = x,
adj = 0, #adjust title to the farthest left
line =2.5 #adjust title up 2.5
)
)
It should be noted that plot is now converted from base R to the oce package for analyzing oceanographic data, but calls the same arguments from base R plot.
The problem becomes that in trying to move the title, the axis labels move as well and overlap. Any suggestions?
Edit: Here is what the image looks like before:
And after:
You might also want to look into the oma= argument in par(), which provides an "outer" margin which can be used to put a nice title. Something like:
library(oce)
data(ctd)
par(oma=c(0, 0, 1, 0))
plot(ctd)
title('Title', outer=TRUE)
This was solved by adding a title argument outside of the plot function as follows:
lapply(names(Cast.files), function (x) plot(Cast.files[[x]],
which = c("temperature", "salinity", "sigmaT","conductivity"),
Tlim = c(11,12),
Slim = c(29,32),
col = "red")
+ title(main = x, adj = 0.48, line = 3.5)#adding the titles at a specific location
)
This allowed for plots that looked like:
If you use the title function, rather than setting main within plot, it would allow you to change the line without affecting anything else in the plot.

Increase space between subplots in Plots.jl

How can I increase the space between subplots in Plots.jl?
Minimal non-working example:
julia> using Plots; pyplot()
Plots.PyPlotBackend()
julia> data = [rand(100), rand(100)];
histogram(data, layout=2, title=["Dataset A" "Dataset B"], legend=false)
ylabel!("ylabel")
If you make the figure small enough, the y label of the second plot collides with the first plot.
In the attributes part of Plots.jl documentation, there is a section called Subplot. There, you will find the keywords margin, top_margin, bottom_margin, left_margin and right_margin that might help you.
Minimal working example would be, then:
using Plots, Measures
pyplot()
data = [rand(100), rand(100)];
histogram(data, layout = 2,
title = ["Dataset A" "Dataset B"], legend = false,
ylabel = "ylabel", margin = 5mm)
Note the using Measures part, by the way. I hope this helps.
Another workaround would be using the bottom_margin keyword argument holding the pyplot backend like this:
using Plots
pyplot()
x1 = rand(1:30, 20);
x2 = rand(1:30, 20);
# subplot 1
p1 = plot(
x1,
label="x1 value",
title="x1 line plot",
ylabel="x1",
bottom_margin=50*Plots.mm,
);
# subplot 2
p2 = plot(
x2,
label="x2 value",
title="x2 line plot",
xlabel="sample",
ylabel="x2",
);
plot(
p1,
p2,
layout=grid(
2,1,
)
)
An alternative is to use the empty figure object _ to occupy the space. It works well when a long legend name overlaps with another subplot with PGFPlotsX backend,
pgfplotsx()
p1 = plot(1:10, label = "a long label name")
p2 = plot(1:10)
plot(p1, p2)
we can use _ in #layout to leave more space for the legend of the first subplot,
plot(p1, p2, layout=#layout([a{0.5w} _ b{0.3w}]))
It can even handle more complicated cases. For example, you might just want to increase the space between two specific subplots instead of all subplots. For example, I use the setting
layout = #layout([grid(2, 1){0.3w} _ grid(2, 1){0.3w} b{0.33w}])
to leave more space via _ for the legend for the left two subplots grid(2,1), but do not touch other subplots.

How to have title in R Vennerable Venn Diagram?

I cannot find anything in documentation here.
Code
library("Vennerable")
data(StemCell)
Vstem <- Venn(StemCell)
Vstem3 <- Vstem[, c("OCT4", "SOX2", "NANOG")]
tl <- "masi"
plot(Vstem3, doWeights = TRUE, type = "circles")
Tried unsuccessfully
plot(..., main = tl)
plot(..., title = tl)
plot(...); title(tl)
plt <- plot(...); title(plt, tl)
Fig. 1 Wrong output without title
R: 3.3.1
OS: Debian 8.5
user20650 answer in comments summarised here. Try (1-2) and choose what fits best.
The plot method is based on the grid package so the normal base R plot approaches to add a title won't work. Looking at the arguments of args(Vennerable:::plotVenn), there doesn't seem a way to add a title and unhelpfully the plots do not return a grid object. So you can just draw a title on the plot window with the following
grid.text("masi", y=0.9, gp=gpar(col="red", cex=2))
As an alternative method, you could grab the grob and then use grid.arrange to plot the title
gridExtra::grid.arrange(grid::grid.grabExpr(plot(Vstem3, doWeights = TRUE,
type = "circles")), top="masi")
The grid.arrange way adds the title as a separate grob, and then they are arranged in two rows. So when resizing the graphics window, it still appears above the plot. This won't be true when drawing straight on the window (as in the first version).
Note: you do not need to use gridExtra, you could do this in grid.
Fig. 1 Output from (1),
Fig. 2 Output from (2)
I think (1) could be better with more adjustments, but now (2) is better.

R How to set tick mark size using a trellis theme in Lattice?

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)

Getting LaTeX into R Plots

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 :)

Resources