How to write an equation with a variable in legend? - r

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.

Related

ggplot x axis label containing subscript and other characters

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

R concatenate differently stylized characters

I'd like to name my plot such as "Plot 1 (p=0.05)".
Please note that the title is bolded and p value is italicized.
I could do manually after plotting contents and do something like:
text(x1, y, "Plot 1", font=2)
text(x2, y, "(p=0.05)", font=3)
However, it's cumbersome to compute coordinates so I'd like to do something like:
title <- (string concatenation here?)
plot(..., main=title)
I failed to find any help on this matter so leave this question here.
Thanks in advance for your help!
I would suggest using the ?plotmath expressions to do your formatting rather than the font= parameters. For example
plot(c(1,3), c(1,3))
text(2,2,expression(bold("Plot 1") ~ (italic("p=.05"))))
Results in
Note that you can't paste() expressions together as easily as you can strings. People often then try to but variables for the parts in quotes but in order to do that, you need to build an expression using bquote() or substitute(). For example
plotname <- "Plot 1"
pvalue <- paste0("p=", formatC(.04944, digits=2, format="f"))
text(2,2,bquote(bold(.(plotname)) ~ (italic(.(pvalue)))))
It is quite simple. Try adding expressions into main=.
like this:
x<- seq(6:1)
y<-c(5,3,77,6,5,1)
main="title", sub="subtitle"
plot(x,y, main=expression(paste(bold("Plot1"), italic("(p=0.05)"))))

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

"abline" doesn't work after "plot" when inside "with"

I want to create a scatterplot and draw the regression line for a subset of a dataset. To give a reproducible example I'll use the CO2 dataset.
I tried this but the regression line doesn't appear for some reason
with(subset(CO2,Type=="Quebec"),plot(conc,uptake),abline(lm(uptake~conc)))
What is the correct way to give a command like this? Can I do it with a one-liner?
You need to provide both your lines of code as a single R expression. The abline() is being taken as a subsequent argument to with(), which is the ... argument. This is documented a a means to pass arguments on to future methods, but the end result is that it is effectively a black hole for this part of your code.
Two options, i) keep one line but wrap the expression in { and } and separate the two expressions with ;:
with(subset(CO2,Type=="Quebec"), {plot(conc,uptake); abline(lm(uptake~conc))})
Or spread the expression out over two lines, still wrapped in { and }:
with(subset(CO2,Type=="Quebec"),
{plot(conc,uptake)
abline(lm(uptake~conc))})
Edit: To be honest, if you are doing things like this you are missing out on the advantages of doing the subsetting via R's model formulae. I would have done this as follows:
plot(uptake ~ conc, data = CO2, subset = Type == "Quebec")
abline(lm(uptake ~ conc, data = CO2, subset = Type == "Quebec"), col = "red")
The with() is just causing you to obfuscate your code with braces and ;.
From ?with: with ... evaluates expr in a local environment created using data. You're passing abline() via .... You need to do something like this:
with(subset(CO2,Type=="Quebec"),{plot(conc,uptake);abline(lm(uptake~conc))})
Gavin and Joshua offer good solutions to your immediate problem; here's the equivalent plot using ggplot:
library(ggplot2)
qplot(conc, uptake, data = CO2[CO2$Type == "Quebec" , ]) + stat_smooth(method = "lm", se = FALSE)

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