11.7 Low-level plotting functions
Low-level plotting functions allow you to add elements, like points, or lines, to an existing plot. Here are the most common low-level plotting functions:
Function | Outcome |
---|---|
points(x, y) |
Adds points |
abline() , segments() |
Adds lines or segments |
arrows() |
Adds arrows |
curve() |
Adds a curve representing a function |
rect() ,polygon() |
Adds a rectangle or arbitrary shape |
text() , mtext() |
Adds text within the plot, or to plot margins |
legend() |
Adds a legend |
axis() |
Adds an axis |
11.7.1 Starting with a blank plot
Before you start adding elements with low-level plotting functions, it’s useful to start with a blank plotting space like the one I have in Figure 11.7. To do this, execute the plot()
function, but use the type = "n"
argument to tell R that you don’t want to plot anything yet. Once you’ve created a blank plot, you can additional elements with low-level plotting commands.
# Create a blank plotting space
plot(x = 1,
xlab = "X Label",
ylab = "Y Label",
xlim = c(0, 100),
ylim = c(0, 100),
main = "Blank Plotting Canvas",
type = "n")
11.7.2 points()
To add new points to an existing plot, use the points()
function. The points
function has many similar arguments to the plot()
function, like x
(for the x-coordinates), y
(for the y-coordinates), and parameters like col
(border color), cex
(point size), and pch
(symbol type). To see all of them, look at the help menu with ?points()
.
Let’s use points()
to create a plot with different symbol types for different data. I’ll use the pirates dataset and plot the relationship between a pirate’s age and the number of tattoos he/she has. I’ll create separate points for male and female pirates:
# Create a blank plot
plot(x = 1,
type = "n",
xlim = c(100, 225),
ylim = c(30, 110),
pch = 16,
xlab = "Height",
ylab = "Weight",
main = "Adding points to a plot with points()")
# Add coral2 points for male data
points(x = pirates$height[pirates$sex == "male"],
y = pirates$weight[pirates$sex == "male"],
pch = 16,
col = transparent("coral2", trans.val = .8))
# Add steelblue points for female data
points(x = pirates$height[pirates$sex == "female"],
y = pirates$weight[pirates$sex == "female"],
pch = 16,
col = transparent("steelblue3", trans.val = .8))
11.7.3 abline()
, segments()
, grid()
Argument | Outcome |
---|---|
h, v |
Locations of horizontal and vertical lines (for abline() only) |
x0, y0, x1, y1 |
Starting and ending coordinates of lines (for segments() only) |
lty |
Line type. 1 = solid, 2 = dashed, 3 = dotted, … |
lwd |
Width of the lines specified by a number. 1 is the default (.2 is very thin, 5 is very thick) |
col |
Line color |
To add straight lines to a plot, use abline()
or segments()
. abline()
will add a line across the entire plot, while segments()
will add a line with defined starting and end points.
For example, we can add reference lines to a plot with abline()
. In the following plot, I’ll add vertical and horizontal reference lines showing the means of the variables on the x and y axes, for the horizontal line, I’ll specify h = mean(pirates$height)
, for the vertical line, I’ll specify v = mean(pirates$weight)
plot(x = pirates$weight,
y = pirates$height,
xlab = "weight",
ylab = "height",
main = "Adding reference lines with abline",
pch = 16,
col = gray(.5, .2))
# Add horizontal line at mean height
abline(h = mean(pirates$height),
lty = 2) # Dashed line
# Add vertical line at mean weight
abline(v = mean(pirates$weight),
lty = 2) # Dashed line
To change the look of your lines, use the lty
argument, which changes the type of line (see Figure 11.9), lwd
, which changes its thickness, and col
which changes its color
You can also add a regression line (also called a line of best fit) to a scatterplot by entering a regression object created with lm()
as the main argument to abline()
:
# Add a regression line to a scatterplot
plot(x = pirates$height,
y = pirates$weight,
pch = 16,
col = transparent("purple", .7),
main = "Adding a regression line to a scatterplot()")
# Add the regression line
abline(lm(weight ~ height, data = pirates),
lty = 2)
The segments()
function works very similarly to abline()
– however, with the segments()
function, you specify the beginning and end points of the segments with the arguments x0
, y0
, x1
, and y1
. In Figure 11.10 I use segments()
to connect two vectors of data:
# Before and after data
before <- c(2.1, 3.5, 1.8, 4.2, 2.4, 3.9, 2.1, 4.4)
after <- c(7.5, 5.1, 6.9, 3.6, 7.5, 5.2, 6.1, 7.3)
# Create plotting space and before scores
plot(x = rep(1, length(before)),
y = before,
xlim = c(.5, 2.5),
ylim = c(0, 11),
ylab = "Score",
xlab = "Time",
main = "Using segments() to connect points",
xaxt = "n")
# Add after scores
points(x = rep(2, length(after)), y = after)
# Add connections with segments()
segments(x0 = rep(1, length(before)),
y0 = before,
x1 = rep(2, length(after)),
y1 = after,
col = gray(0, .5))
# Add labels
mtext(text = c("Before", "After"),
side = 1, at = c(1, 2), line = 1)
The grid()
function allows you to easily add grid lines to a plot (you can customize your grid lines further with lty
, lwd
, and col
arguments):
11.7.4 text()
Argument | Outcome |
---|---|
x , y |
Coordinates of the labels |
labels |
Labels to be plotted |
cex |
Size of the labels |
adj |
Horizontal text adjustment. adj = 0 is left justified, adj = .5 is centered, and adj = 1 is right-justified |
pos |
Position of the labels relative to the coordinates. pos = 1 , puts the label below the coordinates, while 2, 3, and 4 put it to the left, top and right of the coordinates respectively |
With text()
, you can add text to a plot. You can use text()
to highlight specific points of interest in the plot, or to add information (like a third variable) for every point in a plot. For example, the following code adds the three words “Put”, “Text”, and “Here” at the coordinates (1, 9), (5, 5), and (9, 1) respectively. See Figure 11.11 for the plot:
plot(1,
xlim = c(0, 10),
ylim = c(0, 10),
type = "n")
text(x = c(1, 5, 9),
y = c(9, 5, 1),
labels = c("Put", "text", "here"))
You can do some cool things with text()
, in Figure 11.12 I create a scatterplot of data, and add data labels above each point by including the pos = 3
argument:
# Create data vectors
height <- c(156, 175, 160, 172, 159, 165, 178)
weight <- c(65, 74, 69, 72, 66, 75, 75)
id <- c("andrew", "heidi", "becki", "madisen", "david", "vincent", "jack")
# Plot data
plot(x = height,
y = weight,
xlim = c(155, 180),
ylim = c(65, 80),
pch = 16,
col = yarrr::piratepal("xmen"))
# Add id labels
text(x = height,
y = weight,
labels = id,
pos = 3) # Put labels above the points
When entering text in the labels
argument, keep in mind that R will, by default, plot the entire text in one line. However, if you are adding a long text string (like a sentence), you may want to separate the text into separate lines. To do this, add the text \n
where you want new lines to start. Look at Figure 11.13 for an example.
plot(1,
type = "n",
main = "The \\n tag",
xlab = "", ylab = "")
# Text withoutbreaks
text(x = 1, y = 1.3, labels = "Text without \\n", font = 2)
text(x = 1, y = 1.2,
labels = "Haikus are easy. But sometimes they don't make sense. Refrigerator",
font = 3) # italic font
abline(h = 1, lty = 2)
# Text with breaks
text(x = 1, y = .92, labels = "Text with \\n", font = 2)
text(x = 1, y = .7,
labels = "Haikus are easy\nBut sometimes they don't make sense\nRefrigerator",
font = 3) # italic font
11.7.5 Combining text and numbers with paste()
A common way to use text in a plot, either in the main title of a plot or using the text()
function, is to combine text with numerical data. For example, you may want to include the text “Mean = 3.14” in a plot to show that the mean of the data is 3.14. But how can we combine numerical data with text? In R, we can do this with the paste()
function:
The paste function will be helpful to you anytime you want to combine either multiple strings, or text and strings together. For example, let’s say you want to write text in a plot that says The mean of these data are XXX
, where XXX is replaced by the group mean. To do this, just include the main text and the object referring to the numerical mean as arguments to paste()
. In Figure X I plot the chicken weights over time, and add text to the plot specifying the overall mean of weights.
# Create the plot
plot(x = ChickWeight$Time,
y = ChickWeight$weight,
col = gray(.3, .5),
pch = 16,
main = "Combining text with numeric scalers using paste()")
# Add reference line
abline(h = mean(ChickWeight$weight),
lty = 2)
# Add text
text(x = 3,
y = mean(ChickWeight$weight),
labels = paste("Mean weight =",
round(mean(ChickWeight$weight), 2)),
pos = 3)
11.7.6 curve()
Argument | Outcome |
---|---|
expr |
The name of a function written as a function of x that returns a single vector. You can either use base functions in R like expr = $x^2$ , expr = x + 4 - 2 , or use your own custom functions such as expr = my.fun , where my.fun is previously defined (e.g.; my.fun <- function(x) {dnorm(x, mean = 10, sd = 3) ) |
from, to |
The starting (from ) and ending (to ) value of x to be plotted. |
add |
A logical value indicating whether or not to add the curve to an existing plot. If add = FALSE , then curve() will act like a high-level plotting function and create a new plot. If add = TRUE , then curve() will act like a low-level plotting function. |
lty, lwd, col |
Additional standard line arguments |
The curve()
function allows you to add a line showing a specific function or equation to a plot. For example, to add the function \(x^2\) to a plot from the x-values -10 to 10, you can run the code:
If you want to add a custom function to a plot, you can define the function and then use that function name as the argument to expr
. For example, to plot the normal distribution with a mean of 10 and standard deviation of 3, you can use this code:
# Plot the normal distribution with mean = 22 and sd = 3
# Create a function
my.fun <- function(x) {dnorm(x, mean = 2, sd = 3)}
curve(expr = my.fun,
from = -10,
to = 10, lwd = 2)
In Figure~11.14, I use the curve()
function to create curves of several mathematical formulas.
# Create plotting space
plot(1,
xlim = c(-5, 5), ylim = c(-5, 5),
type = "n",
main = "Plotting function lines with curve()",
ylab = "", xlab = "")
# Add x and y-axis lines
abline(h = 0)
abline(v = 0)
# set up colors
col.vec <- piratepal("google")
# x ^ 2
curve(expr = x^2, from = -5, to = 5,
add = TRUE, lwd = 3, col = col.vec[1])
# sin(x)
curve(expr = sin, from = -5, to = 5,
add = TRUE, lwd = 3, col = col.vec[2])
# dnorm(mean = 2, sd = .2)
my.fun <- function(x) {return(dnorm(x, mean = 2, sd = .2))}
curve(expr = my.fun,
from = -5, to = 5,
add = TRUE,
lwd = 3, col = col.vec[3])
# Add legend
legend("bottomright",
legend = c("x^2", "sin(x)", "dnorm(x, 2, .2)"),
col = col.vec[1:3],
lwd = 3)
11.7.7 legend()
Argument | Outcome |
---|---|
x, y |
Coordinates of the legend - for example, x = 0, y = 0 will put the text at the coordinates (0, 0). Alternatively, you can enter a string indicating where to put the legend (i.e.; "topright" , "topleft" ). For example, "bottomright" will always put the legend at the bottom right corner of the plot. |
labels |
A string vector specifying the text in the legend. For example, legend = c("Males, "Females") will create two groups with names Males and Females. |
pch, lty, lwd, col, pt.bg, ... |
Additional arguments specifying symbol types (pch ), line types (lty ), line widths (lwd ), background color of symbol types 21 through 25 (pt.bg ) and several other optional arguments. See ?legend for a complete list |
The last low-level plotting function that we’ll go over in detail is legend()
which adds a legend to a plot. For example, to add a legend to to bottom-right of an existing graph where data from females are plotted in blue circles and data from males are plotted in pink circles, you’d use the following code:
# Add a legend to the bottom right of a plot
legend("bottomright", # Put legend in bottom right of graph
legend = c("Females", "Males"), # Names of groups
col = c("blue", "orange"), # Colors of symbols
pch = c(16, 16)) # Symbol types
In Figure 11.15 I use this code to add a legend to plot containing data from males and females:
# Create plot with data from females
plot(x = pirates$age[pirates$sex == "female"],
y = pirates$tattoos[pirates$sex == "female"],
xlim = c(0, 50),
ylim = c(0, 20),
pch = 16, col = yarrr::transparent("red", .7),
xlab = "Age", ylab = "Tattoos",
main = "Adding a legend with legend()")
# Add data from males
points(x = pirates$age[pirates$sex == "male"],
y = pirates$tattoos[pirates$sex == "male"],
pch = 16, col = yarrr::transparent("blue", .7))
# Add legend
legend("bottomright",
legend = c("Females", "Males"),
col = transparent(c('red', 'blue'), .5),
pch = c(16, 16),
bg = "white")
There are many more low-level plotting functions that can add additional elements to your plots. Here are some I use. To see examples of how to use each one, check out their associated help menus.
plot(1, xlim = c(1, 100), ylim = c(1, 100),
type = "n", xaxt = "n", yaxt = "n",
ylab = "", xlab = "", main = "Adding simple figures to a plot")
text(25, 95, labels = "rect()")
rect(xleft = 10, ybottom = 70,
xright = 40, ytop = 90, lwd = 2, col = "coral")
text(25, 60, labels = "polygon()")
polygon(x = runif(6, 15, 35),
y = runif(6, 40, 55),
col = "skyblue")
text(25, 30, labels = "segments()")
segments(x0 = runif(5, 10, 40),
y0 = runif(5, 5, 25),
x1 = runif(5, 10, 40),
y1 = runif(5, 5, 25),
lwd = 2)
text(75, 95, labels = "symbols(circles)")
symbols(x = runif(3, 60, 90),
y = runif(3, 60, 70),
circles = c(1, .1, .3),
add = TRUE, bg = gray(.5, .1))
text(75, 30, labels = "arrows()")
arrows(x0 = runif(3, 60, 90),
y0 = runif(3, 10, 25),
x1 = runif(3, 60, 90),
y1 = runif(3, 10, 25),
length = .1, lwd = 2)