R has excellent graphics and plotting capabilities, which can mostly be found in 3 main sources: base graphics, the lattice package, the ggplot2 package. The latter two are built on the highly flexible grid graphics package, while the base graphics routines adopt a pen and paper model for plotting, mostly written in Fortran, which date back to the early days of S, the precursor to R (for more on this, see the book Software for Data Analysis - Programming with R by John Chambers, which has lots of very useful information).

Base graphics

For a basic introduction, see the "getting started" page here. Base graphics are very flexible and allow a great deal of customisation, with many individual functions available. However, they lack a coherent underlying framework and, for visualizing highly structured data, are outclassed by lattice and ggplot2.

  • Quick reference info:
    demo("graphics") # Demonstration of graphics in R
    ?plot            # Help page for main plot function
    ?par             # Help page for changing graphical parameters
    ?layout          # Help page on plot arrangement
    example("pch")   # Point style examples
    colours()        # List pre-defined named colours
    ?plotmath        # Help page on plotting maths symbols
  • Useful plotting functions:
    lines, points, abline, curve, text, rug, legend
    segments, arrows, polygon
    locator, identify    # For interacting with plots
  • Create some data for plotting:
    x <- 10 + (1:20)/10
    y <- x^2 + rnorm(length(x))     # Add Gaussian random number
    plot(x, y)
    curve(x^2, add=TRUE, lty=2)     # Add dashed line showing y=x^2
    plot(x, y, type="l", col="blue")  # Plot as blue line (try 'type="o"')
    plot(x, y, type="l", log="xy")   # Plot as line with log X & Y axes:
    abline(v=11, lty=3)    # Add vertical dotted line
    text(11.5, 120, "Hello")   # Add annotation
    legend("topleft", inset=0.05, "data", pch=1, col="blue", bty="n")  # Add a legend
  • Different point styles:
    plot(x, y, pch=2, col="red")  # Hollow triangles
    plot(1:10, rep(1, 10), pch=LETTERS)  # Can also use any character
    example("pch")  # Show point style examples
  • Plot symbols and colours can be specified as vectors, to allow individual specification for each point. R uses recycling of vectors in this situation to determine the attributes for each point, i.e. if the length of the vector is less than the number of points, the vector is repeated and concatenated to match the number required.

  • Single plot symbol (see "?points" for more) and colour (type "colours()" or "colors()" for the full list of predefined colours):
    plot(x, y, pch=2, col="red")  # Hollow triangles
    plot(x, y, pch=c(3, 20), col=c("red", "blue"))  # Blue dots; red "+" signs
    plot(x, y, pch=1:20)   # Different symbol for each point
  • Create vector of contiguous colours in a rainbow palette:
    col <- rainbow(length(x))
    plot(x, y, col=col)
  • Label axes:
    plot(x, y, xlab="Some data", ylab="Wibble")
  • Axis limits are controlled by xlim and ylim, which are vectors of the minimum and maximum values, respectively.

  • Specify axis limits:
    plot(x, y, xlim=c(11, 12), ylim=c(0, 150))
  • Changing the plot layout

    The basic idea behind the R function layout is to divide the plotting device into a series of rows and columns specified by a matrix. The matrix itself is composed of values referring to the plot number, generally just 1,2,3...etc., but can feature repetition.

  • Show simple 2x1 matrix:
    matrix(1:4)                # 4x1
    matrix(1:4, 2, 2)          # 2x2
    matrix(1:6, 3, 2)          # 3x2 ordered by columns
    matrix(1:6, 3, 2, byrow=TRUE)  # 3x2 ordered by rows
  • To view the graphical layout, the following will show the borders of the sub-panels and the number identying each one:
    layout(matrix(1:4, 2, 2))
    layout.show(4)    # Specify layout for 4 panels, for the defined layout
    layout.show(2)    # Try specifying just 2 instead
  • Now fill the layout with 4 plots:
    x <- 1:10
    plot(x, x)
    plot(x, x^2)
    plot(x, sqrt(x))
    plot(x, log10(x))
    curve(log10, add=TRUE)  # Adds to last panel plotted
  • The heights and widths arguments to layout are vectors of relative heights and widths of the matrix rows and columns, respectively.

  • Specifying panels of different sizes:
    layout(matrix(1:4, 2, 2), heights=c(2, 1)); layout.show(4)
    replicate(4, plot(x, x))  # Repeat plot 4 times
  • Plotting a function or equation

    The function curve allows you to plot equations or complex functions, either on their own, or added to an existing plot (with add=T).

  • Plot some analytic expressions:
    curve(x^1)      # "curve(x)" fails! (can also use "curve(I(x))")
    curve(x^2+log10(x)-sin(x))    # Can use arithmetic
    curve(dnorm)    # Normal distribution for mean=0, standard deviation=1
    curve(x^3-x+1, from=-10, to=10, lty=2)  # Specify range & use dashed line
  • Plot a function, with specified arguments:
    curve(dnorm(x, mean=1, sd=2), from=-10, to=10)
  • curve provides the function to be plotted with a vector of x-axis values called x with which to calculate the corresponding y-axis data. If the argument of your function is not called x (e.g. r) , then you need to use the following syntax: curve(myfun(r=x)). The following example illustrates this with a plot of several blackbody curves.

  • First, define a function for the Planck blackbody law to calculate the radiation intensity as a function of wavelength (lambda, in microns) and temperature (Temp, in Kelvin):
    blackbody <- function(lambda, Temp=1e3) {
      h <- 6.626068e-34 ; c <- 3e8; kb <- 1.3806503e-23   # constants
      lambda <- lambda * 1e-6     # Convert from metres to microns
      ( 2*pi*h*c^2 ) / ( lambda^5*( exp( (h*c)/(lambda*kb*Temp) ) - 1 ) )
  • Now plot the curve for the default temperature of 1000K, with some axis labels:
    main <- "Planck blackbody curves"
    xlab <- expression(paste(Wavelength, " (", mu, "m)"))
    ylab <- expression(paste(Intensity, " ", (W/m^3)))
    col <- c("blue", "orange", "red")
    lty <- 1:3
    curve(blackbody(lambda=x), from=1, to=15, main=main, xlab=xlab, ylab=ylab, 
  • Finally, add 2 more curves for 900K and 800K:
    curve(blackbody(lambda=x, T=900), add=T, col=col[2], lty=lty[2])
    curve(blackbody(lambda=x, T=800), add=T, col=col[3], lty=lty[3])
    legtext <- paste(c(1000, 900, 800), "K", sep="")
    legend("topright", inset=0.05, legend=legtext, lty=lty, col=col, text.col=col)
  • Print a copy to a PDF file (the resulting plot can be viewed here):
    dev.copy2pdf(file="blackbody.pdf")  # Also "dev.copy2eps"
  • Interacting with the plot

  • To find out the coordinates at a particular position on a graph, type: locator() then left click with the mouse any number of times within the axes and right click to end; the R prompt will then return and a list will be printed with the X and Y coordinates of the positions clicked. You can retain this information by repeating the above, but with A <- locator() the coordinates will then be stored in A$x and A$y

  • To identify a particular point in a plot, use "identify", e.g:
    x <- 1:10; y <- x^2
    plot(x, y)
    identify(x, y)
    Now left click near one or more points and the element number of that point will be printed at the bottom, left, top or right of the point, depending on which side of it you clicked. Right click inside the axes to finish, and the element numbers of the points identified will be printed, as for locator

    This is more useful if you have named points, in which case identify can print the name instead of the element number, for example:
    names(x) <- LETTERS[1:length(x)]
    plot(x, y)
    identify(x, y, labels=names(x))  # don't forget right click to finish!

  • Lattice graphics

    Lattice is an excellent package for visualizing multivariate data, which is essentially a port of the S software trellis display to R. While it lacks the flexibility and extensibility of ggplot2, it nevertheless represents a great set of routines for quickly displaying complex data with ease. This makes it ideal for use in exploratory data analysis; you can find out more by reading the excellent book Lattice - Multivariate Data Visualization with R by Deepayan Sarkar.

    ggplot2 graphics

    The gg in ggplot2 refers to the book The Grammar of Graphics (which I can highly recommend), by Leland Wilkinson, which has been implemented in an R package by Hadley Wickham. This is another excellent package for multivariate data analysis in R, which is based on a grammatical approach to graphics that provides great flexibility in design. Still under active delevelopment, the only noticeable (and slight) drawback with ggplot2 is the small delay in rendering the final plot. This reflects the fact that there's a lot going on behind the scenes in order to produce such highly polished graphics. The package has an offical website and wiki and you can find out more by reading the excellent book ggplot2 - Elegant Graphics for Data Analysis by Hadley Wickham.

  • Continuing with the data frame of planet properties created above:
    # install.packages("ggplot2")   # package not one of the default R libraries
    require(ggplot2)    # ensure package is loaded
    ggplot(data=A, aes(x=mass, y=sma, label=name, colour=giant, shape=giant)) + 
     geom_point() + 
     scale_x_log10(limits=c(1e23, 1e28)) + 
     scale_y_log10() + 
     geom_text(adj=-0.2, legend=FALSE) + 
     labs(x="Planet mass (kg)", y="Semi-major axis of planet orbit (m)", 
          colour="Type", shape="Type")
  • You can see examples of plotting error envelopes and a multi-panel boxplot created with ggplot2, together with the R code that produced them in the R gallery page.
  • For more examples (with code snippets) of using ggplot2 to create a variety of plots, see the PDF slides from my recent useR! 2011 conference presentation.

  • For further information, you can find out more about how to access, manipulate, summarise, plot and analyse data using R.

    Also, why not check out some of the graphs and plots shown in the R gallery, with the accompanying R source code used to create them.

    Quick links

    Jump to

    Copyright © 2010-2013 Alastair Sanderson