R - Text Formatting of Plot Text that is not hard-wired - r

I would like to add formatted text to a plot (title, axes labels, legend, etc.). A standard solution would be e.g.
plot(1, 1, ylab=substitute(lambda[1]))
where the y-axis label will be the greek letter λ with subscript 1. That is what I want but unfortunatelly it is hard-wired. I would like it to be flexible, i.e. to have an option to pass the text as an argument of a function. So, looking at r help, I found that the argument for substitute is an expression. So I've tried
sometext <- "lambda[1]"
e <- parse(text="sometext")
plot(1, 1, ylab=substitute(e))
But substitute ignores that e is an object an simply prints the text 'e' as the label. So instead I tried
plot(1, 1, ylab=eval(e))
which was better because eval at least evaluates the expression but the label now is literally 'lambda[1]', i.e. it is not evaluated as a greek letter λ with a subscript.
I then explicitly stated that 'e' is an expression doing
e <- expression(sometext)
and running the two previous plot commands but with the same results as before.
The closest I came to what I wanted ot achieve was doing
plot(1, 1, ylab=substitute(var[i], list(var="lambda", i=1)))
where at least the 1 is printed as a subscript but the text 'lambda' instead of the greek letter λ is printed.
Any suggestions on how can I achieve what the first command does but not hard-wired? E.g. using a string and somehow converting it to the right object so that it will be displayed properly? Thanks.
Daniel

You can pass the label as an expression like so and then use substitute inside the function:
dwat <- function(expr){
plot(1, 1, ylab = substitute(expr))
}
dwat(lambda[1])
dwat(mu[2])
If you want to pass a string instead of an expression use parse:
dwat_string <- function(string){
plot(1, 1, ylab = parse(text = string))
}
dwat_string("mu[1]")
Another option would be to use the ellipsis approach. That way you can pass an xlab or any other argument to plot:
dwat2 <- function(...){
plot(1, 1, ...)
}
dwat2(ylab = expression(lambda[1]))

you were close, checks if this works
substitute(lambda[i],list(i=i))

Related

Plot the positive infinity symbol and negative infinity symbol

I was wondering how I can plot the positive infinity sign and -Infinity sign in plot?
Here is my R code (with no success):
plot(1, ty ='n', ann = F, xlim = c(-4, 6), ylim = c(-3.5, 1.5) )
text(c(-4, 6 ), rep(1, 2), c( bquote(- infinity ), bquote(infinity ) ) )
?plotmath starts
If the text argument to one of the text-drawing functions (text,
mtext, axis, legend) in R is an expression, the argument is
interpreted as a mathematical expression and the output will be
formatted according to TeX-like rules.
and the labels parameter of text is documented as
a character vector or expression specifying the text to be written. An
attempt is made to coerce other language objects (names and calls) to
expressions, and vectors and other classed objects to character
vectors by as.character.
(emphasis mine). bquote does not actually return an expression (the R class, not the concept), but a language object (a call, specifically). This is causing two problems:
Because R can't handle a vector of calls, c does not actually create a vector, but instead coerces the result to a list, akin to how c(sum, mean) is coerced to a list, and
While text would coerce the call returned from bquote itself to an expression (which would get parsed properly), it coerces the list to a character vector, which does not get interpreted according to plotmath.
You could coerce the list of calls produced with c and bquote explicitly with as.expression, but it's quicker to just call expression directly and avoid bquote altogether:
plot(1, ty ='n', ann = F, xlim = c(-4, 6), ylim = c(-3.5, 1.5))
text(c(-4, 6 ), rep(1, 2), expression(-infinity, infinity))
As an end note, c actually does work on multiple expressions—sort of—in that c(expression(-infinity), expression(infinity)) returns expression(-infinity, infinity). Unlike bquote, which has two named parameters, expression takes ... though, so it's easier to just call it once with multiple inputs.
Try:
text(c(-4, 6 ), rep(1, 2), c( bquote("- \U221E"), bquote("\U221E") ) )

In R, why is there awkward output in the legend when I am using paste() instead of c() in addition to pretty10exp()?

I'm trying to make the legend of this plot pretty, so I need there the be an actual superscript, which is why I am using the pretty10exp() function from the sfsmisc library. It works when I use the c() function.
However, I am also trying to keep the string and the scientific notation number on the same line. The legend() is broken into two lines, which I think is due to c(). I thought I could use paste(), but for some reason the output is now incorrect.
plot(1:12)
pVal <- 4
legend("topright", legend = c("P value:", sfsmisc::pretty10exp(pVal)), cex = 1.5)
legend("topright", legend = paste("P value:", sfsmisc::pretty10exp(pVal)), cex = 1.5)
pVal being an arbitrary number represented in scientific notation. The second line results in output like this: "P value: (significand) %*% 10^-4". The first line also doesn't give me what I want. How can I fix this problem?
pretty10exp returns an expression which allows it to use the ?plotmath features for making nice looking numbers. When working with expressions, you can't just paste values in like strings. You need to manipulate them with a special set of functions. One such function is substitute. You can do
plot(1:12)
pVal <- 4
legend("topright", cex = 1.5,
legend = substitute("P value: "*x, list(x=sfsmisc::pretty10exp(pVal)[[1]])) )
We use substitute() to take the value contained in the expression from pretty10exp and prefix it with the label you want. (We use * to concatenate rather than paste() since plotmath allows it)
This is what I would do:
fun <- function(text, pVal) {
y <- floor(log10(pVal))
x <- pVal / 10^y
bquote(.(text)*":" ~ .(x) %.% 10 ^ .(y))
}
plot.new()
text(0.5,0.7,fun("P value", 0.4))
text(0.5, 0.3, fun("P value", signif(1/pi, 1)))
No package is needed.

How to evaluate a variable as an expression for axis label in R?

Objective is to allow user to pass a string to a plotting function and have it evaluated correctly as plotmath.
Question is how to combine an evaluated expression with other string text.
It seems the presence of any other string or expression nullifies the evaluation of the label.
Example:
label1 <- 'degree~C'
plot(1:10, type='l', xlab=bquote(.(parse(text=label1)))) #evaluated correctly
plot(1:10, type='l', xlab=bquote('Some text'~~Omega^2~~.(parse(text=label1)))) #missing degree C
Here is the output of the second plot showing that label1 is missing:
Expected output:
Other (possibly misguided) attempts:
plot(1:10, type='l', xlab=substitute(paste('Some text'~~Omega^2~~mystring), list(mystring=label1))) #string not evaluated
plot(1:10, type='l', xlab=substitute(paste('Some text'~~Omega^2~~mystring), list(mystring=parse(text=label1)))) #string missing entirely
plot(1:10, type='l', xlab=substitute(paste('Some text'~~Omega^2~~mystring), list(mystring=expression(text=label1)))) #string missing entirely
Similar: Evaluate expression given as a string
Just use eval(parse(text=label1)), like the linked answer suggests, or more simply, paste("First part", label1).

R legend pch mix of character and numeric

Is it possible to use a mix of character and number as plotting symbols in R legend?
plot(x=c(2,4,8),y=c(5,4,2),pch=16)
points(x=c(3,5),y=c(2,4),pch="+")
legend(7,4.5,pch=c("+",16),legend=c("A","B")) #This is the problem
Use the numerical equivalent of the "+" character:
plot(x=c(2,4,8),y=c(5,4,2),pch=16)
points(x=c(3,5),y=c(2,4),pch="+")
legend(7,4.5,pch=c(43,16),legend=c("A","B"))
There are actually numerical equivalents for all symbols!
Source: Dave Roberts
The pch code is the concatenation of the Y and X coordinates of the above plot.
For example, the + symbol is in row (Y) 4 and column (X) 3, and therefore can be drawn using pch = 43.
Example:
plot(x=c(2,4,8),y=c(5,4,2),pch=16)
points(x=c(3,5),y=c(2,4),pch="+")
legend(7,4.5,pch=c(43,16),legend=c("A","B"))
My first thought is to plot the legend twice, once to print the character symbols and once to print the numeric ones:
plot(x=c(2,4,8),y=c(5,4,2),pch=16)
points(x=c(3,5),y=c(2,4),pch="+")
legend(7,4.5,pch=c(NA,16),legend=c("A","B")) # NA means don't plot pt. character
legend(7,4.5,pch=c("+",NA),legend=c("A","B"))
NOTE: Oddly, this works in R's native graphical device (on Windows) and in pdf(), but not in bmp() or png() devices ...
I bumped to this issue several time, so I wrote a tiny function below. You can use to specify the pch value, e.g.
pch=c(15:17,s2n("|"))
String to Numeric
As noted in previous answers, you can simply add the numerical equivalent of the numeric and character symbols you want to plot.
However, just a related aside: if you want to plot larger numbers (e.g., > 100) or strings (e.g., 'ABC') as symbols, you need to use a totally different approach based on using text().
`Plot(x,y,dat,type='n') ; text(x,y,labels = c(100,'ABC')
Creating a legend in this case is more complicated, and the best approach I've ever come up with is to stack legends on top of each other and using the legend argument for both the pch symbol and the description:
pchs <- c(100,'ABC','540',sum(13+200),'SO77')
plot(1:5,1:5,type='n',xlim=c(1,5.1))
text(1:5,1:5,labels = pchs)
legend(3.5,3,legend = pchs,bty='n',title = '')
legend(3.5,3,legend = paste(strrep(' ',12),'ID#',pchs),bty='n',title='Legend')
rect(xleft = 3.7, ybottom = 1.5, xright = 5.1, ytop = 3)
This uses strrep to concatenate spaces in order to shift the text over from the "symbols", and it uses rect to retroactively fit a box around the printed legend text.

How to add nice formated anotations to a R base graph using expression and the value of a variable?

Say, I have a variable rv which has some numerical value. Now, I want to plot the value of this variable on a base plot but preceded by a nicely formatted symbol e.g., r subscript m, using expression. To write on the plot I use mtext.
However, what I get is either the value of the variable, but no nicely formatted symbol (left annotation), or a nicely formatted symbol, but not the value of the variable, but the variable name...
I tried to play around with eval, but didn't get what I wanted. Here is my code:
plot(1:10, rep(10,10), ylim=c(0,12))
rv <- 0.43
#left annotation:
mtext(paste(expression(italic(r[M])), " = ", rv), side = 1, line = -1.5, adj = 0.1)
#right annotation:
mtext(expression(paste(italic(r[M]), " = ", rv)), side = 1, line = -1.5, adj = 0.9)
This is the result:
How do i get both, nice format and value of the variable? Thanks.
btw: I know that I can get it, if I use two times mtext and play around with adj and stuff. But I would really like to get it in one call or without playing around with the position of two annotations.
The bquote function will create an expression and alow substitution of values using .(var) syntax. for your case do something like:
text( 5,1, bquote( italic(r[M]) == .(rv) ) )
Just combine what you have and plot two pieces, joined by using adj:
R> plot(1:10, rep(10,10), ylim=c(0,12))
R> text(2,12, expression(paste(italic(r[M]))), adj=1)
R> text(2,12, paste("=", rv), adj=0)

Resources