Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Put a frame around the title in a generic R plot

Tags:

plot

r

I have a framed plot with a title. I was wondering if there is a quick and easy way to put also a frame around the (main) title of plot.

The frame should have the same width as the frame around the plot. Is there also a way to adjust the height of the frame?

I would like to stick to the generic plot function.

# Some example data
x <- rnorm(10)
y <- rnorm(10)

# Plot data and add title
plot(x,y, 
     xlab = "",
     ylab = "",
     frame = TRUE
     )
title( main = "This should be framed")

Many thanks and a nice weekend to everybody!

like image 599
Peanut Avatar asked Feb 20 '16 18:02

Peanut


2 Answers

One possibility is to use rect.

First use par("usr") to get "the extremes of the user coordinates of the plotting region".

Because you want that the "frame should have the same width as the frame around the plot", the x-positions are straightforward: use the first and second values of the 'user coordinates' as xleft and xright.

The bottom and top positions of the rect require some more work. The y position of the title "defaults to being vertically centered in (outer) margin 3" (?title). Use par("mai") to get the margins in inches. Calculate the midpoint of the top y margin by dividing margin 3 by 2 (par("mai")[3] / 2). Define a height of the frame to e.g. 0.5, which corresponds to halfway between the center of the title and the border of the figure region and the plot region respectively.

To convert from inches to user coordinates, use grconvertY. That is, we multiply the value in inches by diff(grconvertY(y = 0:1, from = "inches", to = "user")) (see e.g. here). This value is then added to the upper user coordinate of y (coord[4]).

coord <- par("usr")
y_mid <- par("mai")[3] / 2
height <- 0.5
conv <- diff(grconvertY(y = 0:1, from = "inches", to = "user"))

rect(xleft = coord[1],
     xright = coord[2],
     ybottom = coord[4] + (y_mid * (1 - height) * conv),
     ytop = coord[4] + (y_mid * (1 + height) * conv),
     xpd = TRUE)

enter image description here

like image 82
Henrik Avatar answered Oct 03 '22 15:10

Henrik


The grid graphical system has much better facilities for handling units, so I'd be tempted to use the gridBase package to "step into" a graphical system in which the rectangle's shape and position can be more directly named. Here's what that might look like:

library(grid)
library(gridBase)

## Standard idiom for setting your frame of reference to be that of the base R plot's frame
lapply(baseViewports(), pushViewport)
## Draw a rectangle centered 2 lines above frame and 1.5 lines of text in height
grid.rect(y = unit(1,"npc") + unit(2, "lines"), 
          height = unit(1.5, "lines"), just = "center")

enter image description here

Unlike Henrik's base R solution, this won't require you to fiddle around by hand for each plot, experimenting until you get the rectangle's y-coordinates just right.

like image 43
Josh O'Brien Avatar answered Oct 03 '22 17:10

Josh O'Brien