ggplot x axis label containing subscript and other characters - r

I wish to label the x-axis of a volcano plot I made using EnhancedVolcano as "Log2(B/A)" where 2 is a subscript, and B/A is a character vector I define as X.axis. Xlab is one of the arguments of EnhancedVolcano function.
I tried:
X.axis <- "(B/A)"
log2 <- expression(~Log[2])
xlab = paste(log2,X.axis)
Result was ~Log[2](B/A)
I also tried:
log2 <- expression(~Log[2]~X.axis)
xlab = log2
This gave Log2 X.axis.
What am I doing wrong?

X.axis <- "B/A"
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
scale_x_continuous(name = bquote(Log[2] * bgroup("(", .(X.axis), ")" )))
Alternatively, you can do a more-apparent fraction, though it is easier (given what little I know of your available variables) to do it statically:
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
scale_x_continuous(name = bquote(Log[2] * bgroup("(", over(B, A), ")" )))
I admit to not knowing all of the differences between using expression(.) and bquote(.) for labels and such. They return different class objects (expression and call, respectively) but can be used interchangeably in many cases, but the latter supports (for instance) value replacement (the .(X.axis) above), something I find very useful.

Explanation of my comments to r2evans:
The advantage of bquote over expression is that its embedded, accessory function cryptically named "." allows one to access values of named objects that exist in the calling frame. The expression function never evaluates the symbols or tokens that are placed in its list of arguments. The disadvantage of bquote is that it will not accept multiple arguments. To return multiple arguments as an expression list/vector with bquote, one needs to deploy it with an sapply or lapply call.
The bquotewith. function-combo solved the puzzle that was facing the OP who wanted the value of X.axis but instead only got its name in the printed result of the expression call. Keeping the various levels of meaning straight is a challenge to new users of R. The introduction of the tidyverse solved that challenge in some settings by collapsing the layers to some extent, but probably delays acquisition of understanding ordinary "standard evaluation" in R.
The tilde operator inside an argument to expression is handled by the plotmath engine as a space. Notice that r2evans did not use a tilde but rather used an asterisk "*", because it is also a valid separator to delimit the tokenization process by the R parser, but it leaves no "space" in the plotmath output. The `tilde operator has many, diverse uses in R. It can be a function returning a formula, a spacing operator in a plotmath expression or a couple of different connector un a tidyverse evaluation

Related

passing arguments to geom_point2 with mapply

My objective is pass lists as arguments to the function geom_point2 using lapply or analogously mapply. In similar situations, I had success passing a list (or lists) to geom_cladelabel as in:
mapply(function (x,y,z,w,v,u,t,s) geom_cladelabel(node=x, label=y,
align=F, etc. # Where x y z etc are lists.
Problem is related to the use of aes inside geom_point2. (not in geom_cladelabel):
In the case of geom_point2, the node info is inside aes, and I could't do it. Normally I do not get any error message, but it does not work.
The objective is to make this example work, but using mapply instead of writting geom_point2 two times.
# source("https://bioconductor.org/biocLite.R")
# biocLite("ggtree")
library(ggtree)
library(ape)
#standard code
newstree<-rtree(10)
node1<-getMRCA(newstree,c(1,2))
node2<-getMRCA(newstree,c(3,4))
ggtree(newstree)+
geom_point2(aes(subset=(node ==node1) ), fill="black", size=3, shape=23)+
geom_point2(aes(subset=(node ==node2) ), fill="green", size=3, shape=23)
#desire to substitute the geom_point2 layers with mapply or lapply:
#lapply(c(node1,node2), function (x) geom_point2(aes(subset=(node=x)))))
Here is a solution calling geom_point2 usig mapply:
library(ggtree)
ggtree(rtree(10)) +
mapply(function(x, y, z)
geom_point2(
aes_string(subset=paste("node ==", x)),
fill=y,
size=10,
shape=z
),
x=c(11,12),
y=c("green", "firebrick"),
z=c(23,24)
) +
geom_text2(aes(subset=!isTip, label=node))
The solution is in the aes_string(), which writes the value of x directly in the aesthetics. The default aes() does not pass on the value of x, but just the string "x". When plotting, ggtree then looks for a node called "x", and ends with an empty node list.
I guess this has to do with the variable being stored in the mapply-environment and not being passed on to the plot.
PS: Sorry for my too quick answer with do.call() earlier. It is useful, but off-topic here.

How to write an equation with a variable in legend?

I am trying to write an equation like "R^2=0.00575" in the legend, and the number 0.00575 can be embedded in the legend automatically. Here is an example.
set.seed(100)
x=rnorm(100)
y=1:100
fit=lm(y~x)
R_squared=format(summary(fit)$r.squared,digits = 3)
plot(x,y,type="l")
legend("topleft",legend =expression(R^{2}~"="~R_squared),bty = "n")
As the figure shows, the variable "R_squared" is not embedded in the equation. Is there any solution? Thanks.
For this task I think it is best to do parse(text=sprintf(...)). You can code the R language syntax into the string literal to be parsed into an R expression using parse(), and use sprintf() format specifications to embed any numeric or string values that are stored in variables into the expression.
set.seed(100L);
x <- rnorm(100L);
y <- 1:100;
fit <- lm(y~x);
R_squared <- format(summary(fit)$r.squared,digits=3L);
plot(x,y,type='l');
legend('topleft',legend=parse(text=sprintf('paste(R^2,\' = %s\')',R_squared)),bty='n');
An alternative syntax that leverages the fact that == is plotted as a single equal sign:
legend('topleft',legend=parse(text=sprintf('R^2 == %s',R_squared)),bty='n');
See the plotmath documentation.
You can also use bquote:
set.seed(100L);
x <- rnorm(100L);
y <- 1:100;
fit <- lm(y~x);
R_squared <- format(summary(fit)$r.squared,digits=3L);
plot(x,y,type='l');
legend('topleft',legend=bquote(R^{2} ~ "=" ~ .(R_squared)),bty='n');
More information on partial substitution of expressions with bquote can be found here, which defines the function as:
An analogue of the LISP backquote macro. bquote quotes its argument
except that terms wrapped in .() are evaluated in the specified where
environment.

How can you use ggplot to superimpose many plots of related functions in an automatic way?

I have a family of functions that are all the same except for one adjustable parameter, and I want to plot all these functions on one set of axes all superimposed on one another. For instance, this could be sin(n*x), with various values of n, say 1:30, and I don't want to have to type out each command individually -- I figure there should be some way to do it programatically.
library(ggplot2)
define trig functions as a function of frequency: sin(x), sin(2x), sin(3x) etc.
trigf <- function(i)(function(x)(sin(i*x)))
Superimpose two function plots -- this works manually of course
ggplot(data.frame(x=c(0,pi)), aes(x)) + stat_function(fun=trigf(1)) + stat_function(fun=trigf(2))
now try to generalize -- my idea was to make a list of the stat_functions using lapply
plotTrigf <- lapply(1:5, function(i)(stat_function(fun=function(x)(sin(i*x))) ))
try using the elements of the list manually but it doesn't really work -- only the i=5 plot is shown and I'm not sure why when that's not what I referenced
ggplot(data.frame(x=c(0,pi)), aes(x)) +plotTrigf[[1]] + plotTrigf[[2]]
I Thought this Reduce might handle the 'generalized sum' to add to a ggplot() but it doesn't work -- it complains of a non-numeric argument to binary operator
Reduce("+", plotTrigf)
So I'm kind of stuck both in executing this strategy, or perhaps there's some other way to do this.
Are you using version R <3.2? The problem is that you actually need to evaluate your i parameter in your lapply call. Right now it's being left as a promise and not getting evaulated till you try to plot and at that point i has the last value it had in the lapply loop which is 5. Use:
plotTrigf <- lapply(1:5, function(i) {force(i);stat_function(fun=function(x)(sin(i*x))) })
You can't just add stat_function calls together, even without Reduce() you get the error
stat_function(fun=sin) + stat_function(fun=cos)
# Error in stat_function(fun = sin) + stat_function(fun = cos) :
# non-numeric argument to binary operator
You need to add them to a ggplot object. You can do this with Reduce() if you just specify the init= parameter
Reduce("+", plotTrigf, ggplot(data.frame(x=c(0,pi)), aes(x)))
And actually the special + operator for ggplot objects allows you to add a list of objects so you don't even need the Reduce at all (see code for ggplot2:::add_ggplot)
ggplot(data.frame(x=c(0,pi)), aes(x)) + plotTrigf
The final result is
You need to use force in order to make sure the parameter is being evaluated at the right time. It's a very useful technique and a common source of confusion in loops, you should read about it in Hadley's book http://adv-r.had.co.nz/Functions.html
To solve your question: you just need to add force(i) when defining all the plots, inside the lapply function, before making the call to stat_function. Then you can use Reduce or any other method to combine them. Here's a way to combine the plots using lapply (note that I'm using the <<- operator which is discouraged)
p <- ggplot(data.frame(x=c(0,pi)), aes(x))
lapply(plotTrigf, function(x) {
p <<- p + x
return()
})

Use Tex expression in R `main` label

I'm plotting a histogram in R and I want to include a $\bar{X}$ expression in the main argument of hist and combine it with the value of a dynamically calculated variable average.
x <- rnorm(100, 1, 1)
average <- mean(x)
hist(x, main=paste("Average $\bar{X}=", average))
That SO doesn't work and I spent hours trying to get it working with an expression statement or a substitute statement, both of which I dont find a case in the examples where the value of a variable is substituted in the text.
This solution uses * to paste text and expressions and uses substitute to replace 'average' with the calculated value.
hist(x, main = substitute("Average "*bar(x)*" = "*average, list(average=average)))
Try:
hist(x, main=bquote(Average~bar(X)==.(average) )
bquote's main use is to "import-and-evaluate" named values from the global (or enclosing) environment(s) into an expression which would otherwise not be evaluating its tokens. You could add spaces to make the expression more readable but the parser ignores them:
hist(x, main=bquote( Average ~ bar(X) == .( average ) )
If you need extra spaces use multiple tilde's: ~~~
It's rather interesting to look at the code for bquote (easy since it's not hidden):
bquote

how to show $\{ X_t \}$ in the title of a plot of R

How to show $\{ X_t \}$ of Latex in the title of a plot of R?
For example
plot(slot(x,"GRID"),slot(x,"PATH"),type="l", xlab="Time t",ylab="X",
main=paste("Simulation of \{X_t\}"))
Thanks!
Assuming you will provide meaningful arguments for the slot expressions, then I think there is a reasonable chance that this is what you want:
plot(1:10,1:10,type="l", xlab="Time t",ylab="X",
main=expression("Simulation of {"*X[t]*"}"))
This is a plotmath expression that presents "t" as a subscript of "X" and that expression is enclosed in curley braces. If I have misread your request, then note that the "*" character is a separator in the plotmath syntax and the braces are simply characters than can be deleted. (The LaTeX expressions don't make a lot of sense to those of us who just use the plotmath syntax, so describing what you want in prose or mathematical jargon would work better for any clarifications.)
To have R emulate LaTeX typesetting, see the examples and methods described in ?plotmath.
To actually have LaTeX typeset your plot text, use the tikz() graphics device provided by the tikzDevice package.
The group() plotmath function can be used to formalise DWin's answer. This solution has the advantage (IMHO) of not using strings as part of the expression. Instead we use the ~ operator to add spacing (whitespace is ignored).
plot(1:10, 1:10, type = "l", xlab = "Time t", ylab = "X",
main=expression(Simulation ~ of ~ group("{", X[t], "}")))
The bgroup() plotmath function provides scalable delimiters but is used in the same manner as the example code above.
Edit (In response to ran2's comment):
The same approaches can be used in ggplot and lattice, using the power of plotmath, just as with base graphics. E.g.
require(ggplot2)
df <- data.frame(A = 1:10, B = 1:10)
qplot(A, B, data = df,
main = expression(Simulation ~ of ~ group("{", X[t], "}")))

Resources