knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.align = 'center', fig.height = 3, fig.width = 3 )
graphics
and grDevices
packagesgraphics
contains a number of functions for creating and formatting plotsplot
, which (usually) draws scatter plotsplot.new
)# a single numeric vector # elements are plotted against their indices v <- 1:10 plot(1:10) # two numeric vectors vs <- sample(v) plot(x = v, y = vs) # a matrix # the first two columns are plotted as if they were x and y, the others are ignored m <- matrix(1:12, 4, 3) m plot(m) # a data frame # every column is plotted against every other, creating a matrix of scatter plots d <- iris[3:5] plot(d)
par
function, which is called internally by plot
par
are passed through ...
?par
for a full list of available parameters; here are some examples:\newline
type
decides the plot type, e.g. points, lines or bothplot(v, vs, type = 'p') plot(v, vs, type = 'l') plot(v, vs, type = 'b')
pch
sets the plotting character for pointsplot(1:25, rep(1, 25), pch = 1:25)
pch
is a vectorized operationpch
was the same as that of x
but pch
will be recycled if necessaryplot(1:25, rep(1, 25), pch = 1:5)
lty
controls line typeplot(v, vs, type = 'l', lty = 1) plot(v, vs, type = 'l', lty = 2) plot(v, vs, type = 'l', lty = 3)
col
col
can be specified in a number of ways:# as a hex code plot(v, vs, pch = 16, col = "#6495ED") # as a character string # see colors() for a list of available colors plot(v, vs, pch = 16, col = "cornflowerblue") # as a factor; each level is given a color based on the current palette f <- factor(rep(letters[1:2], each = 5)) plot(v, vs, pch = 16, col = f) # as an integer, which is interpreted as an index in the current palette plot(v, vs, pch = 16, col = 2)
rainbow
colorRampPalette
palette
NOTE: colorRampPalette
is a function that returns a function which takes an integer as argument and returns a vector of that many interpolated colors.
plot(v, vs, pch = 16, col = colorRampPalette(c('royalblue1', 'yellow', 'purple'))(10))
xlim
and ylim
set the axes limitsplot(v, vs, xlim = c(-2, 12))
points
or lines
plot(v, vs) points(v, sample(v), pch = 20, col = 'green')
plot
type
parameter, so you can draw lines with points
abline
adds a straight line to an existing plota
and b
describe its intercept and slope, respectively (slope is the tangent of the angle between the line and the X axis)v
and h
draw vertical and horizontal lines, respectively, and determine their crossing points with the respective axesplot(log(0:2000 / 100), type = 'l') abline(h = 0) plot(log(0:2000 / 100), type = 'l') abline(h = c(0,1), lty = c(1,2))
cex
parametercex
is the multiplier to that default sizeplot(v, vs, pch = 16) # cex alone refers to the plotting characters plot(v, vs, pch = 16, cex = 2) # other cex parameters exist for other plot elements plot(v, vs, pch = 16, cex.lab = 2)
xlab
and ylab
change axis labelsplot(v, vs, xlab = 'label x', ylab = 'label y')
main
sets the plot titleplot(v, vs, main = 'plot title')
title
plot(v, vs) title('plot title')
legend
adds a legend boxplot(v, vs, col = f, pch = 16) title('plot title') legend('topright', legend = levels(f), col = 1:length(levels(f)), pch = 16, cex = 0.75)
las
controls the orientation of axis labelsmfrow
, mfpar
and layout
, of which I only use the latterlayout
takes a matrix of integers as argument mat
mat
are 1 through the number of plots to be drawnlength(mat)
fieldsmat
plot
call will create a new window with the same layoutm <- matrix(c(1, 1, 2, 1, 1, 2, 3, 3, 4), 3, 3, byrow = T) m layout(mat = m)
layout.show(n)
shows which field in the current layout the n-th plot will appear in
here is an example (wrapped in a function to work within the vignette):
foo <- function() { # prepare layout layout(mat = m) # prepare data v1 <- rnorm(1e4) v2 <- runif(1e4, -1, 1) d1 <- density(v1) d2 <- density(v2) names(d2) <- c(names(d2)[2], names(d2)[-2]) # draw plots plot(v1, v2, pch = 4, cex = 0.5) plot(d2, main = '', xlab = '', ylab = '') plot(d1, main = '', xlab = '', ylab = '') # draw an empty plot in field 16 plot.new() } foo()
\newline
layout(mat = 1)
plot
plot
doessmoothScatter
plot(rnorm(1e4), runif(1e4), pch = 4, cex = 0.2) smoothScatter(rnorm(1e4), runif(1e4), pch = 4, cex = 0.2)
barplot
beside = TRUE
plot
on a factor will draw a barplot# a vector barplot(v) # a matrix barplot(m) barplot(m, beside = T)
stripchart
# a vector rv <- rnorm(1e2) stripchart(rv, pch = 20) stripchart(rv, method = 'jitter', pch = 20) # a data frame stripchart(iris[1:4], method = 'jitter', vertical = T, pch = 1)
NOTE: This is implemented better in package beeswarm
.
boxplot
outlying data points are highlighted
boxplots are drawn with boxplot
varwidth
argument makes the box width proportional to sample sizenotch
creates indentations in boxes: if these do not overlap, the means are "significantly different"# a vector boxplot(rnorm(1e3)) # a matrix boxplot(as.matrix(iris[1:4])) #a data frame boxplot(iris[1:4])
hist
functionbreaks
argument controls the number of binshist
also returns the plot as an object that can be drawn alter with print
hist(rnorm(1e5)) hist(rnorm(1e5), breaks = 100)
persp
draws a surfacecontour
draws contoursimage
draws a color-coded matrixpersp(volcano) contour(volcano) image(volcano)
data
data
is undefined, the formula will be evaluated in the Global Environmentsubset
argumentdata
subset
function can be informative hereplot
can also evaluate the col
argument with NSEplot
# numeric vs numeric draws a scatter plot plot(Sepal.Length ~ Sepal.Width, data = iris, col = Species, pch = 20) # numeric vs factor drawas a boxplot plot(Sepal.Length ~ Species, data = iris, col = Species) # two terms on RHS draws two plots plot(Sepal.Length ~ Petal.Length + Petal.Width, data = iris) # plot one column vs all others plot(Sepal.Length ~ ., data = iris, col = Species, pch = 20)
barplot(yield ~ variety + year, data = lattice::barley, subset = site == 'Morris', beside = TRUE) stripchart(Sepal.Length ~ Species, data = iris, vertical = T, method = 'jitter', pch = 1) boxplot(Sepal.Length ~ Species, data = iris)
coplot
uses more complex formulas to separate data into subplotscoplot(Sepal.Length ~ Sepal.Width | Species, data = iris, pch = 16, rows = 1)
lattice
packagelibrary(lattice) xyplot(Sepal.Length ~ Petal.Width | Species, data = iris, layout = c(3,1)) stripplot(yield ~ year | site, data = barley, layout = c(3,2)) bwplot(yield ~ year | variety, data = barley, layout = c(5,2)) bwplot(Sepal.Length ~ Species, data = iris) histogram(~ Sepal.Length | Species, data = iris, layout = c(3,1)) levelplot(Sepal.Length ~ Petal.Width * Petal.Length | Species, data = datasets::iris, layout = c(3,1), at = seq(4, 8, length.out = 100), col.regions = colorRampPalette(c('blue', 'gray90', 'red'))(100), aspect = 1)
NOTE: lattice
plots ignore some par
commands, e.g. title
, layout
.
ALSO NOTE: lattice
plots are only drawn automaticaly when in an interactive session. Otherwise they must be drawn explicitly with print
.
The simplest way to save a plot to a file is to draw it in RStudio viewer and press the "Export file" button in the viewer but where is the fun in that? You will also find the viewer rather slow in some cases.
R has a system of devices that graphics is streamed to. The default device is the null device. Graphics sent to the null device ends up in the RStudio viewer in the Plots tab. Other devices can be opened at any time to send the graphics to a file. Opening a new device creates a file to capture the incoming graphics. That device becomes the current device, where the graphics will be sent now. Functions that open devices include jpeg
, png
and pdf
, each for the corresponing file type.
All currently open devices can be viewed with dev.list()
. A newly open device is added to the end of the list and becomes the current one. It can be viewed with dev.cur()
. There are ways to switch between devices but that is rarely done. Usually one opens a device, streams the graphics and closes the device immediately after.
Devices are closed with the dev.off
function. It will close the device specified by a number, that device's number on the list. Called without an argument, dev.off()
, it will close the current device. Only when a device is closed is the corresponding file saved. Attempts to manipulate the file before that will throw errors. Opening a stream to a file that is already associated with a graphics device, which can happen when plotting fails and one wants to immediately try again, is a sure way to trouble. Sometimes a dev.off()
needs to be redoubled.
graphics.off
closes all open devices. The null device can never be closed. graphics.off()
skips it and dev.off(1)
throws an error. Calling dev.off()
on a null device will also clear the plots from RStudio memory.
To print a plot to a file open a device with, say, png
, draw a plot as you normally would in RStudio, and call dev.off()
to close the file. Unlike in RStudio, past plots are not available for rewinding. Only the last plot is saved to the file. The pdf
device behaves differently. It has an onefile
argument, which is set to TRUE
by default. With the pdf device plots will be added to the file, one plot per page. Again, the graphics cannot be viewed before the device is closed.
Also, .pdf files are saved as vetor graphics rather than rasters. You can open them in Corel or Illustrator and edit particular elements there with no loss of quality.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.