BuddhaWithBigBelly
BuddhaWithBigBelly

Reputation: 345

R - how to combine expression(), paste() and formatC() commands for one legend element?

I am trying to set up a nice legend. It should include the greek letter mu, I can do this with expression, some literals, i.e. ":" and "mm", and a coefficient of a model formatted with formatC. What i get running without problems is either to have no greek letter, then I can use simple paste command

leg.txt <- c("Number of Points:"
           ,formatC(length(dist),big.mark=" ")
           ,"Normal distribution"
           ,paste(mu,":",formatC(fit$estimate[1], digits = 3,format = "f"),"mm")
           ,paste(expression(sigma),":",formatC(fit$estimate[2], digits = 3,format = "f"),"mm")
           ,"Density plot"
           ,paste(expression(bar(x)),":",formatC(mean, digits = 3,format = "f"),"mm")
           ,paste("SD:",formatC(sd, digits = 3,format = "f"),"mm")
           )


legend("topleft",  leg.txt
     ,col= c("white","white","blue","white","white","red","white","white")
     ,bty = "n"
     ,lwd = c(2,2)  

)

this leads to something like

(Cannot post picture due to reputation)

mu: 0.283 mm

But as it can be seen, no Greek letters are included. Switching to something like

leg.txt <- c("Number of Points:"
           ,formatC(length(dist),big.mark=" ")
           ,"Normal distribution"
           ,eval(substitute(expression(paste(mu, ":" , c, "mm"),list(c=(formatC(fit$estimate[1], digits = 3,format = "f"))))))
           ,paste(expression(sigma),":",formatC(fit$estimate[2], digits = 3,format = "f"),"mm")
           ,"Density plot"
           ,paste(expression(bar(x)),":",formatC(mean, digits = 3,format = "f"),"mm")
           ,paste("SD:",formatC(sd, digits = 3,format = "f"),"mm")
           )digits = 3,format = "f"))))))

leads to y:cmm (formatC($(fit,estimate)_1,3,f))

I have the problem that after 2 hours of researching I am not able, to make mu either appear as a greek expression, or if I do, then the formatC() will not be evaluated, it will be instead posted like a literal instead of giving a formatted number.

Used all hints from other posts, like bquote etc. but could not make it running.

Edited some "more runnable" examples. This is Code which does not run:

x <- seq(1,100,1)
y <- runif(100)
y2 <- x + y 

fit <- lm(y2~x)
plot(x,y2)
abline(fit, col = "red",lwd = 2)
mu2    <- formatC(fit$coefficients[1], digits = 3,format = "f")
sigma2 <- formatC(fit$coefficients[2], digits = 3,format = "f")
mean <- mean(y2)
sd <- sd(y2)
leg.txt <- c("Number of Points:"
             ,formatC(length(dist),big.mark=" ")
             ,"Normal distribution"
             ,bquote(mu ~ ":" ~ .(mu2) ~ "mm")
             ,bquote(sigma ~ ":" ~ .(sigma2) ~ "mm")
             ,"Density plot"
             ,paste(expression(bar(x)),":",formatC(mean, digits = 3,format = "f"),"mm")
             ,paste("SD:",formatC(sd, digits = 3,format = "f"),"mm")
)
legend("topleft",  leg.txt
       ,col= c("white","white","blue","white","white","red","white","white")
       ,bty = "n"
       ,lwd = c(2,2)  
)

The problem happens when i use bquote the second time.

What runs is

x <- seq(1,100,1)
y <- runif(100)
y2 <- x + y 

fit <- lm(y2~x)
plot(x,y2)
abline(fit, col = "red",lwd = 2)
mu2    <- formatC(fit$coefficients[1], digits = 3,format = "f")
sigma2 <- formatC(fit$coefficients[2], digits = 3,format = "f")
mean <- mean(y2)
sd <- sd(y2)
leg.txt <- c("Number of Points:"
             ,formatC(length(dist),big.mark=" ")
             ,"Normal distribution"
             ,bquote(mu ~ ":" ~ .(mu2) ~ "mm")
             ,expression(paste(sigma,":",eval(formatC(fit$estimate[2], digits = 3,format = "f"))),"mm")
             ,"Density plot"
             ,paste(expression(bar(x)),":",formatC(mean, digits = 3,format = "f"),"mm")
             ,paste("SD:",formatC(sd, digits = 3,format = "f"),"mm")
)
legend("topleft",  leg.txt
       ,col= c("white","white","blue","white","white","red","white","white")
       ,bty = "n"
       ,lwd = c(2,2)  
)

Still I think that bquote is the way to go. In my real data I am fitting a normal distribution, but that should not matter.

Error I get by using bquote two times is: argument legend is missing with no default (translated from german error message, but seems to be right. The legend object gets no txt, though it is in my workspace.

Solution which is now working finally is:

x <- seq(1,100,1)
y <- runif(100)
y2 <- x + y 

fit <- lm(y2~x)
plot(x,y2)
abline(fit, col = "red",lwd = 2)
mu2    <- formatC(fit$coefficients[1], digits = 3,format = "f")
sigma2 <- formatC(fit$coefficients[2], digits = 3,format = "f")
mean <- mean(y2)
sd <- sd(y2)
leg.txt <- c("Number of Points:"
             ,formatC(length(dist),big.mark=" ")
             ,"Normal distribution"
             ,as.expression(bquote(mu ~ ":" ~ .(mu2) ~ "mm"))
             ,as.expression(bquote(sigma ~ ":" ~ .(sigma2) ~ "mm"))
)
legend("topleft",  leg.txt
       ,col= c("white","white","blue","white","white","red","white","white")
       ,bty = "n"
       ,lwd = c(2,2)  
)

Upvotes: 2

Views: 3954

Answers (2)

IRTFM
IRTFM

Reputation: 263301

This is another approach using an sapply( expr-vector, as.expression) approach that I saw on Rhelp years ago. I cannot remember which of the gurus to thank (probably one of Ligges, Grothendieck, Murdoch, Dalgaard). It allows the use of bquote constructed expressions and avoids the use of plotmath-paste which I see as a major advantage in readablity.

plot(x,y2)
abline(fit, col = "red",lwd = 2)
leg.txt <- sapply( c("Number of Points:"
             ,bquote(.(formatC(length(dist),big.mark=" ")))
             ,"Normal distribution"
             ,bquote(mu ~ ":" ~ .(mu2) ~ mm)
             ,bquote(sigma~":"~.(formatC(fit$estimate[2], digits = 3,format = "f"))~mm)
             ,"Density plot"
             ,bquote(bar(x)*":"*.(formatC(mean, digits = 3,format = "f"))*mm)
             ,bquote(SD*":"*.(formatC( sd, digits = 3,format = "f"))*mm)
), as.expression)


legend("topleft",  legend=leg.txt
       ,col= c("white","blue","white","white","red","white","white")
       ,bty = "n"
       ,lwd = c(2,2)  
)

Upvotes: 1

Aaron - mostly inactive
Aaron - mostly inactive

Reputation: 37734

You use substitute to include both "math" and numeric variables, as in ?plotmath. But here there was also something unexpected; the vector of elements for the legend didn't combine properly unless one of them was an expression, so here I just made one of your plain text lines into an expression.

fit <- list(estimate=c(1.35456, 2.63454))
dist <- 1:10
mean <- 10.3456
sd <- 0.1566

leg.txt <- c(paste("Number of Points:",formatC(length(dist),big.mark=" "))
                   ,expression("Normal distribution")
                   ,substitute(paste(mu,": ",x," mm"), 
                        list(x=formatC(fit$estimate[1], digits = 3,format = "f")))
                   ,substitute(paste(sigma,": ",x," mm"), 
                        list(x=formatC(fit$estimate[2], digits = 3,format = "f")))
                   ,"Density plot"
                   ,substitute(paste(bar(x),": ",y," mm"), 
                        list(y=formatC(mean, digits = 3,format = "f")))
                   ,substitute(paste("SD: ",x," mm"), 
                        list(x=formatC(sd, digits = 3,format = "f")))
           )

plot(1:5,1:5)
legend("topleft",  legend=leg.txt
     ,col= c("white","blue","white","white","red","white","white")
     ,bty = "n"
     ,lwd = c(2,2)  
)

Upvotes: 1

Related Questions