################################################################################ ### R BASICS WORKSHOP ### ### PRESENTATION 8: GRAPHICS ### ### ### ### Center for Conservation and Sustainable Development ### ### Missouri Botanical Garden ### ### Website: rbasicsworkshop.weebly.com ### ################################################################################ ### INTRODUCTION ############################################################### # R offers an incredible variety of options for building graphics. Type this # into the console to see a few available options: demo (graphics) # A better version of the volcano figure (from the help of function *image*): x <- 10 * (1:nrow(volcano)) y <- 10 * (1:ncol(volcano)) image(x, y, volcano, col = terrain.colors(100), axes = FALSE) contour(x, y, volcano, levels = seq(90, 200, b = 5), add = TRUE, col = "peru") axis(1, t = seq (100, 800, b = 100)) axis(2, t = seq (100, 600, b = 100)) box() title(main = "Maunga Whau Volcano", font.main = 4) # This part of the workshop is divided into the following sections: # A. High level functions # B. Low level functions # C. Graphic parameters modified by the function *par* # D. Opening multiple windows and dividing a window into panels # E. Saving graphics as files ### A. HIGH LEVEL FUNCTIONS #################################################### # high level graphical functions are used to create figures, while low level # functions are used to modify or add items to figures # Here we will look at some examples, but for a slightly longer list of functions # consult pages 40 and 41 of "R for Beginners" (available at the website) data(iris) str(iris) ## *plot* is a generic function used to make many types of graphs. # A generic function works differently depending on the type of arguments it is # given. However, this function is most frequently used to create scatter-plots plot(iris$Sepal.Length ~ iris$Sepal.Width) plot(iris$Petal.Length ~ iris$Petal.Width) # There are many arguments that can be used in the function *plot* and # other functions to modify figures. Some of the most common are: # type: type of graph # pch: shape of the symbol # col: color of the symbol # bg: background color of the symbol # main: main title # xlab and ylab: titles of the axes # cex.lab: font size of axis titles # cex.axis: size of text on the axes # las: controls the orientation of the text on the y axis # bty: change the type of box around points plot (iris$Petal.Length ~ iris$Petal.Width, cex = 3) plot (iris$Petal.Length ~ iris$Petal.Width, cex = 2, pch = 21, col = "black", bg = "gray") plot (iris$Petal.Length ~ iris$Petal.Width, cex = 3, pch = 21, col = "black", bg = "gray", main = "Plot of Petal Petals vs. Width Length", xlab = "Petal Width", ylab = "Petal Length", cex.lab = 1.5, cex.axis = 1.5, bty = "l", las = 1) ## These are other common graphics functions ## # *boxplot* makes boxplots boxplot(iris$Sepal.Length) boxplot(iris$Sepal.Length ~ iris$Species) boxplot(iris$Sepal.Length ~ iris$Species, col = "gold", horizontal = TRUE, las = 1) boxplot (iris$Sepal.Length ~ iris$Species, names = expression(italic("Iris setosa"), italic("Iris versicolor"), italic("Iris virginica")), xlab = "Sepal length (cm)", col = "gold", cex.lab = 1.5, cex.axis = 1.5) ? boxplot # *hist* makes histograms hist(iris$Sepal.Length) range(iris$Sepal.Length) hist(iris$Sepal.Length, breaks = seq(min(iris$Sepal.Length), max(iris$Sepal.Length), length.out = 30), col = "darkolivegreen", border = "white") hist(iris$Sepal.Length, breaks = seq(min(iris$Sepal.Length), max(iris$Sepal.Length), length.out = 30), col = "darkolivegreen", border = "white", xlab = "Sepal Length", freq = FALSE) # *pie* o *piechart* creates piecharts table(iris$Species) pie(x = table(iris$Species)) # *barplot* makes bar charts barplot(height = table(iris$Species)) rand <- sample(letters, 300, replace = TRUE) table(rand) barplot(table(rand)) ### B. LOW LEVEL FUNCTIONS ##################################################### # Here, we will use the functions *points*, *lines* and *legend*. To see # a more extensive list of low-level graphics functions see "R for Beginners" # *type = "n"* is often used to create an empty graph plot(iris$Petal.Length ~ iris$Petal.Width, type = "n") plot (iris$Petal.Length ~ iris$Petal.Width, xlab = "Petal Width", ylab = "Petal Length", cex.lab = 1.5, cex.axis = 1.5, bty = "l", las = 1, type = "n") # *points* adds points to a chart created by *plot* points (iris$Petal.Length[iris$Species == "setosa"] ~ iris$ Petal.Width[iris$Species == "setosa"]) points(iris$Petal.Length[iris$Species == "setosa"] ~ iris$Petal.Width[iris$Species == "setosa"], pch = 19, cex = 1.5, col = "lightblue") points(iris$Petal.Length[iris$Species == "versicolor"] ~ iris$Petal.Width[iris$Species == "versicolor"], pch = 19, cex = 1.5, col = "darkorange") points(iris$Petal.Length[iris$Species == "virginica"] ~ iris$Petal.Width[iris$Species == "virginica"], pch = 19, cex = 1.5, col = "grey50") # *lines* adds lines to a graph lines(x = c(0, 2.5), y = rep(mean(iris$Petal.Length[iris$Species == "setosa"]), times = 2), col = "royalblue4", lwd = 3) lines(x = c(0, 2.5), y = rep(mean(iris$Petal.Length[iris$Species == "versicolor"]), 2), col = "orange", lwd = 3) lines(x = c(0, 2.5), y = rep(mean(iris$Petal.Length[iris$Species == "virginica"]), 2), col = "black", lwd = 3) # *legend* adds a legend legend(x = "topleft", legend = c(expression(italic("Iris setosa")), expression(italic("Iris versicolor")), expression(italic("Iris virginica"))), pch = 19, col = c("lightblue", "darkorange", "grey50"), cex = 1.3) legend(x = 1.3, y = 2.3, legend = c(expression(italic("Iris setosa")), expression(italic("Iris versicolor")), expression(italic("Iris virginica"))), pch = 19, col = c("lightblue", "darkorange", "grey50"), cex = 1.3) legend(x = 10.3, y = 20.3, legend = c(expression(italic("Iris setosa")), expression(italic("Iris versicolor")), expression(italic("Iris virginica"))), pch = 19, col = c("lightblue", "darkorange", "grey50"), cex = 1.3) ### C. GRAPHICAL PARAMETERS MODIFIED BY FUNCTION *par* #################### # To have greater control over graphics, it is necessary to know the function # *par* and its associated arguments. # Many features of graphics can be specified using the function *par* or inside # functions like *plot* (e.g. color). Others can be specified only using *par* # (e.g. size of the margin). The help for function *par* has a lot of useful # information: help(par) # First version: hist(iris$Sepal.Length, breaks = seq(0, 8, 0.5), col = "gray70", border = "gray40", xlab = "", ylab = "", main = "", axes = FALSE, ylim = c(0,40)) hist(iris$Petal.Length, breaks = seq(0, 8, 0.5), density = 10, add = TRUE) axis(side = 1, t = seq(0, 8, 1), cex.axis = 2, lwd = 2, las = 1) axis(side = 2, t = seq(0, 40, 5), cex.axis = 1.5, cex.axis = 2, lwd = 2, las = 1) mtext(text = "Length (cm)", side = 1, line = 3, cex = 2) mtext(text = "Specimens", side = 2, line = 3, cex = 2) legend(x = "topright", legend = c("Sepals", "Petals"), fill = c("gray70", "black"), density = c(NA, 30), pt.cex = 2, border = c("gray40", "black"), cex = 2) # In this first version, there is an obvious problem with the title on the # y axis. To fix this, we can use the argument *mar* in function *par*. # Second version: par(mar = c(5, 5, 4, 2), family = "mono") # This is the only line that is different hist(iris$Sepal.Length, breaks = seq(0, 8, 0.5), col = "gray70", border = "gray40", xlab = "", ylab = "", main = "", axes = FALSE, ylim = c(0, 40)) hist(iris$Petal.Length, breaks = seq(0, 8, 0.5), density = 30, add = TRUE) axis(side = 1, t = seq(0, 8, 1), cex.axis = 2, lwd = 2, las = 1) axis(side = 2, t = seq(0, 40, 5), cex.axis = 1.5, cex.axis = 2, lwd = 2, las = 1) mtext(text = "Length (cm)", side = 1, line = 3, cex = 5) mtext(text = "Specimens", side = 2, line = 3.5, cex = 0.5) legend(x = "topright", legend = c("Sepals", "Petals"), fill = c("gray70", "black"), density = c(NA, 30), pt.cex = 2, border = c("gray40", "black"), cex = 1.5, bty = "n") ### D. OPENING MULTIPLE WINDOWS AND DIVIDING A WINDOW INTO PANELS ############## ## 1. How to open multiple windows ## # If there is no active window (graphical device), a high level graphical # function will create a one. plot(iris$Petal.Length ~ iris$Petal.Width, pch = 19) # To open more than one viewport can use the *dev.new* dev.new() plot(iris$Sepal.Length, iris$Sepal.Width, pch = 19, col = "red") ## Consult the help for *dev.new* to find out about related functions ## 2. Create a window with multiple panels *par* ## # The argument *mfrow* in *par* needs 2 numbers: the number of rows and columns # in the used to divide the window: par(mfrow = c (1,2)) plot(iris$Petal.Length ~ iris$Petal.Width, pch = 19) plot(iris$Sepal.Length, iris$Sepal.Width, pch = 19, col = "red") par(mfrow = c (2,1)) plot (iris$Petal.Length ~ iris$Petal.Width, pch = 19) plot(iris$Sepal.Length, iris$Sepal.Width, pch = 19, col = "red") ## 3. Create a window with multiple panels *layout* ## # *layout* is a function that can also split a window into panels, but the # panels do not have to be the same size or organized in rows and columns # The main argument for *layout* is a matrix defining how the window will be # divided: div <- matrix(1:3, nrow = 3, ncol = 1) div layout(mat = div) layout.show(3) plot (iris$Sepal.Length, iris$Sepal.Width, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Sepal width (cm)") plot (iris$Sepal.Length, iris$Petal.Length, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Petal length (cm)") plot (iris$Sepal.Length, iris$Petal.Width, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Petal width (cm)") div <- matrix(1:4, nrow = 2, ncol = 2, byrow = TRUE) div layout(mat = div) layout.show(4) plot (iris$Sepal.Length, iris$Sepal.Width, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Sepal width (cm)") plot (iris$Sepal.Length, iris$Petal.Length, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Petal length (cm)") plot (iris$Sepal.Length, iris$Petal.Width, pch = 19, cex.lab = 1.5, cex.axis = 1.5, xlab = "Sepal length (cm)", ylab = "Petal width (cm)") plot(iris$Sepal.Length, iris$Petal.Width, pch = 19, type = "n", axes = FALSE, bty = "n", xlab = "", ylab = "") mtext("Sepal length", line = -3, cex = 1.5) mtext("versus", line = -5, cex = 1.5) mtext("other variables", line = -7, cex = 1.5) mtext("in Anderson's Iris", line = -9, cex = 1.5) # This is a simple graph with two panels div <- matrix(1:2, nrow = 1, ncol = 2) layout(mat = div) layout.show(2) plot(iris$Sepal.Length, iris$Sepal.Width) plot(iris$Sepal.Length, iris$Petal.Length) # What if we want to make one panel to be "inside" the other div <- matrix(c(1,1,2,1), nrow = 2, ncol = 2) div layout(mat = div) layout.show(2) plot(iris$Sepal.Length, iris$Sepal.Width) plot(iris$Sepal.Length, iris$Petal.Length) # In addition, the arguments * * heights and widths * * We can resize # The cells in columns or rows layout(mat = div, widths = c(2, 1), heights = c(1, 2)) layout.show(2) plot(iris$Sepal.Length, iris$Sepal.Width) plot(iris$Sepal.Length, iris$Petal.Length) ### E. SAVE GRAPHICS AS FILES ################################################## # Just like it is possible to send a graphic to an open window, it is possible # to send a graphic to an open file (both are types of "graphical devices"). # While *new.dev()* opens a window, there are several functions that open # various types of iles: *jpeg*, *png*, *tiff*, *bmp*, *pdf*, *postscript* # Example using *png* help(png) getwd() # see what the working directory # Use *setwd* or the menus in R to choose an appropriate working directory ## First version ## # Step 1. Open the file: png(filename = "SepalLenght_vs_SepalWidth.png") # Step 2. Create a figure into the file plot(iris$Petal.Length ~ iris$Petal.Width, cex = 3, pch = 21, col = "black", bg = "gray", main = "Plot of Petal Petals vs. Length Width", xlab = "Petal Width", ylab = "Petal Length", cex.lab = 1.5, cex.axis = 1.5, bty = "l", las = 1) # Step 3. Close the file dev.off() ## Second Version ## # In this version we have the figure much larger and better quality png(filename = "SepalLenght_vs_SepalWidth_2.png", width = 480 * 13, height = 480 * 10, pointsize = 12 * 1.5, res = 600) plot(iris$Petal.Length ~ iris$Petal.Width, cex = 3, pch = 21, col = "black", bg = "gray", main = "Plot of Petal Petals vs. Width Length", xlab = "Petal Width", ylab = "Petal Length", cex.lab = 1.5, cex.axis = 1.5, bty = "l", las = 1) dev.off()