Adding a newline in a substitute() expression - r

I'm trying to annotate a plot in ggplot with relevant data from a regression model.
I've followed the suggestions in this SO post and tried to modify the function to have a couple additional items in a newline in the plot.
This is my attempt at a new function:
lm_eqn = function(m){
eq <- substitute(italic(y) == a %.% italic(x)^b*","~~italic(r)^2~"="~r2*","~~italic(n)~"="~nn*","~~italic(p-value)~"="~pv,
list(a = format(exp(coef(m)[1]), digits = 3),
b = format(coef(m)[2], digits = 3),
r2 = format(summary(m)$r.squared, digits = 3),
nn=format(summary(m)$df[2]),
pv=format(summary(m)$coefficients[,4][2])))
as.character(as.expression(eq));
}
It produces the expected output: all in one line. But I'd like to split the text in two lines, the second one starting with italic(n)=. But if I introduce a \n, it throws an error when it finds \n. If I introduce the \n inside the quotes: "\n" then it seems to be ignored and the text remains in one line. I haven't found any reference as to how to introduce a newline in such an expression. Your kind help will be much appreciated.
Thanks.
EDIT: following a coment by #Tim I present a rewriten code and adjusted question.

\n cannot be used in plotmath expressions. You could perhaps break the expression in two parts, and use annotate to add the expressions where you want them. Or, use atop. Check out this post ->
Line break in expression()?

Related

bquote, parsing, expression to get multiple lines labels in ggplot with greek letters and variables as subscripts

Let's say I have
paste0("Year = ",index,"\nN = ",length((dfGBD %>% filter(year==index))[[vbl]]),
" Bandwidth = ",round(stats::bw.nrd(log((dfGBD %>% filter(year == index))[[vbl]])),2),
"\nSkewness:", round(e1071::skewness(log((dfGBD %>% filter(year==index))[[vbl]])), 2),
" Kurtosis:",round(e1071::kurtosis(log((dfGBD %>% filter(year==index))[[vbl]])),2),
"\nmu[",vbl,"] = ", round(mean((dfGBD %>% filter(year==index))[[vbl]]),2),
" sigma[",vbl,"] = ",round(sd((dfGBD %>% filter(year==index))[[vbl]]),2)
)
inside a sapply through index years. Further, vbl is a string with the name of a variable. The sapply produces a vector of labels for a factor variable.
Applying ggplot I obtain labels similar to the next:
Year = 2000
N = 195 Bandwidth = 0.09
Skewness: 0 Kurtosis: -0.56
mu[Mortality] = 7750.85 sigma[Mortality] = 1803.28
Till here, all ok. I have already written mu[vbl], sigma[vbl] thinking in parsing and subscript notation to get the greek letters with the name of the variable saved in vbl as subscript.
First I tried facet_wrap with option labeller = "label_parsed". I obtained an error which I only solved writting the string between backticks ``, but then \n has no effect. I tried many options using bquote and/or parse and/or expression and/or atop etc. in order to get this multiple lines result with the desired output I described above. But only get or one line or very ugly outputs or, mostly, errors, and I couldn't see yet the greek letters.
So what/how should I do?
PS: as answered in other stackoverflow's, \n does not work in this context, so a list with bquote's for each line is suggested. I tried it, but then I got an error that I think is due to incompatibility of number of elements of all the lists and number of labels of a factor (a label may not be a list?).
Thank you!

r bquote: remove the space before approximately equal plotmath symbol

This is almost what I want as a plot heading:
plot(1:10)
ylabs<-c("All","Native","Exotic")
i=1
mtext(bquote("("*.(letters[i])*")"~.(ylabs[i])~"("%~~%italic("H'")*")"),side=3)
But I don't want the space after "(" and before the approx. equal sign. Adding the * separator before the symbol gives an error
mtext(bquote("("*.(letters[i])*")"~.(ylabs[i])~"("*%~~%italic("H'")*")"),side=3)
Error: unexpected SPECIAL in
even though the * separator works in other parts of bquote. I can get the right spacing by including the approx. equal symbol directly
mtext(bquote("("*.(letters[i])*")"~.(ylabs[i])~"("*"≈"~italic("H'")*")"),side=3)
but I would like to know if there's a way to get * to work before the plotmath symbol?
I tried this with expression instead of bquote, but couldn't get it to combine the characters with the indexed objects.
The trick is to put the entire text into a subscript:
plot(1:10)
ylabs<-c("All","Native","Exotic")
i=1
b <- bquote(phantom(0)["("*.(letters[i])*")"~.(ylabs[i])~"(" %~~%italic("H'")*")"])
mtext(b, cex = 2, side=3)

R: How do I write "≥2: n=nrow(x)" in plot legend?

I am doing boxplots and have problems with the legend. Specifically, I want to write "≥2: n=formatC(nrow(x))" but can not combine the commands for the ≥ symbol, the function that calculates nrow(x) and formatC(nrow(x), bigmark=",") that should give the nrow number with a thousand separator.
What I tried so far:
smoke <- matrix(c(1:1200),ncol=1,byrow=TRUE)
colnames(smoke) <- c("High")
smoke <- as.table(smoke)
pdf('test.pdf')
plot(NA,xlim=c(0,100),ylim=c(0,100))
legend(10,70,bquote(paste(NA>=2, ": n=", .(formatC(nrow(smoke)), big.mark=","))))
dev.off()
which gives: ≥ 2: n=1200
I would like to have: ≥2: n=1,200
It seems that formatC does not work under bquote and I would also like to remove the space after the ≥ symbol.
I also tried:
legend(x,y, legend=c(expression(NA>=2), paste(": n=", formatC(nrow(smoke)), sep="")))
which gives the legend in two lines:
≥ 2
: n=1200
Putting paste before expression gives one line but does not convert the >= to ≥.
I am exporting the graph as pdf, which currently works for the ≥ symbol. I would prefer to keep that. Unicode does not work with pdf in my hands.
Thanks in advance,
Philipp
You have a ) in the wrong place right after smoke, so it takes the big.mark argument as part of paste and not formatC. Try this:
legend(10,70,bquote(paste(NA>=2, ": n=", .(formatC(nrow(smoke), big.mark=",")))))

R - Plot: How to format in 10-base scientific notation and put it text, mtex, title etc functions?

I have numeric variable, say K=3.5e-5 (its values is calculated throughout my script). I want to write this value somewhere (title, as text in the plot, etc) in my plot as:
K_{root} = 3.5 10^{-5} cm /d
I have tried the functions bquote, substitute and no one worked.
Let's put the question in examples. I have tried the following:
1)
png("exp_1.png")
kroot = 3.5e-5
plot(1:10,1:10,
text(4,9,bquote(italic(K[root])~"="~.(kroot)~"cm/d")))
dev.off()
Try my favorite function, paste().
plot(1:10,1:10,
text(4,9,gsub("e",paste("K[root]=",format(k,scientific=TRUE),"cm/d",sep=" "),replacement=" 10^")))
You can replace the "e" here using the function gsub. I've edited my answer to include this.
The output:
> k=.0000035
> k
[1] 3.5e-06
> gsub("e",paste("K[root]=",format(k,scientific=TRUE),"} cm/d",sep=" "),replacement=" 10^{ ")
[1] "K[root]= 3.5 10^{ -06 } cm/d"
You can remove the extra spaces around { -06 } by using the function substr, if it's important, or simply leave out the curly brackets in the gsub statement.
I try to avoid using paste inside expressions. There is generally a cleaner way to approach this:
expon <- floor(log10(kroot)) # returns -5
mantis <- kroot*10^(-1*expon ) # returns 3.5
plot(1:10,1:10,
text(4,9,substitute( italic(K[root]) == mantis %.% pten* expon ~cm/d,
list(expon=expon, mantis=mantis, pten=" 10^")))

multiline comment() attributes for functions

Say I have the following function:
sqrt_x = function(x) {
sqrtx = x^0.5
return(list("sqrtx" = sqrt))
}
attr(sqrt_x, "comment") <- "This is a comment to be placed on two different lines"
if I type
comment(sqrt_x)
I get
[1] "This is a comment to be placed on two different lines"
what I want, however, is that the comment is returned on two different lines (it could also be more lines and different comment elements. Any ideas appreciated.
As Andrie stated: you need to insert newline characters.
If you don't want to have to manually specify where the newlines go, then you can use strwrap to create breaks at convenient points, so that your string doesn't exceed a specified width.
msg <- strwrap("This is a comment to be placed on two different lines", width = 20)
cat(msg, sep = "\n")
# This is a comment
# to be placed on two
# different lines
A complete solution could look something like:
#Add comment as normal
comment(sqrt_x) <- "This is a comment to be placed on two different lines"
#Display using this function
multiline_comment <- function(x, width = getOption("width") - 1L)
{
cat(strwrap(comment(x), width = width), sep = "\n")
}
multiline_comment(
sqrt_x,
20
)
You can use \n to insert a newline. The cat method shows this in the way you want:
attr(sqrt_x, "comment") <- "This is a comment to be placed on two\ndifferent lines"
cat(comment(sqrt_x))
This is a comment to be placed on two
different lines
This is a bit of a hack, and maybe not what you want, but if you provide a multi-element character vector, and the lines are long enough that R's default formatting decides they should be on multiple lines, you may get what you want:
comment(sqrt_x) <- c("This is a comment ",
"to be placed on two different lines")
comment(sqrt_x)
## [1] "This is a comment "
## [2] "to be placed on two different lines"
You could use format to pad automatically:
comment(sqrt_x) <- format(c("This is a comment",
"to be placed on two different lines"),
width=50)
(as shown elsewhere you could also use strwrap() to break up a single long string
into parts)
If you're absolutely desperate to have this and you don't like the extra spaces, you could mask the built-in comment function with something like #RichieCotton's multiline version:
comment <- function(x,width = getOption("width") - 1L) {
cat(strwrap(base::comment(x), width = width), sep = "\n")
}
but this is probably a bad idea.

Resources