Text labels with background colour in R

Viewed 10907

I was wondering if there is a simple way to add text labels with a contrasting background to an R plot using the base graphic system. Until now I have always used the rect() function together with graphics::strheight() and graphics::strwidth() to separately create the background box on which I then place my text using text():

# Prepare a noisy background:
plot(x = runif(1000), y = runif(1000), type = "p", pch = 16, col = "#40404050")

## Parameters for my text:
myText <- "some Text"
posCoordsVec <- c(0.5, 0.5)
cex <- 2

## Background rectangle: 
textHeight <- graphics::strheight(myText, cex = cex)
textWidth <- graphics::strwidth(myText, cex = cex)
pad <- textHeight*0.3
rect(xleft = posCoordsVec[1] - textWidth/2 - pad, 
        ybottom = posCoordsVec[2] - textHeight/2 - pad, 
        xright = posCoordsVec[1] + textWidth/2 + pad, 
        ytop = posCoordsVec[2] + textHeight/2 + pad,
        col = "lightblue", border = NA)

## Place text:
text(posCoordsVec[1], posCoordsVec[2], myText, cex = cex)

This is the result:

Text with background

This does the job but it is quite tedious and you run into trouble when you start using pos, adj, offset etc. to tweak the positioning of the text. I am aware of TeachingDemos::shadowtext() to make text stand out from the background but this adds an outline instead of a box.

I am looking for a simple way to create text with a background box, something like text(x, y, labels, bg = "grey20"). I can't be the first person to require such a functionality and I am probably just missing something obvious. Help is appreciated. Thanks

4 Answers

Quick hack using altcode character for a box:

plot(x=runif(1000), y=runif(1000), 
     type="p", pch=16, col="#40404050")

labels <- c("some text", "something else")

boxes <- sapply(nchar(labels), function(n) 
  paste(rep("\U2588", n), collapse=""))

pos <- rbind(c(0.2, .1), c(.5, .5))
text(pos, labels=boxes, col="#CCCCCC99")
text(pos, labels=labels, family = "mono")

Bless your hardworking hearts, but plotrix has boxed.labels():

# Prepare a noisy background:
plot(x = runif(1000), y = runif(1000), type = "p", pch = 16, col = "#40404050")

## Parameters for my text:
myText <- "some Text"
posCoordsVec <- c(0.5, 0.5)
cex <- 2

## Background rectangle: 
textHeight <- graphics::strheight(myText, cex = cex)
textWidth <- graphics::strwidth(myText, cex = cex)
pad <- textHeight*0.3


## Place text:
plotrix::boxed.labels(posCoordsVec[1], posCoordsVec[2], myText, cex = cex, 
      border = NA, bg ="lightblue", xpad = 1.4, ypad = 1.4)

boxed.labels example

Related