Base Graphics in R (part II) STAT 133 Gaston Sanchez CC BY-SA 4.0 Base Graphics 2 / 72 Graphics in R Traditional Graphics I I I R "graphics" follows a static, ”painting on canvas” model. Graphics elements are drawn, and remain visible until painted over. For dynamic and/or interactive graphics, R is limited. 3 / 72 Traditional Graphics Traditional graphics model In the traditional model, we create a plot by first calling a high-level function that creates a complete plot, and then we call low-level functions to add more output if necessary 4 / 72 Dataset mtcars head(mtcars) ## ## ## ## ## ## ## Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout Valiant mpg cyl disp hp drat wt qsec vs am gear carb 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 5 / 72 Scatter plot # simple scatter-plot plot(mtcars$mpg, mtcars$hp) 250 ● ● ● ● ● ● 150 ● ● ● ●●● ●● ● ● ● ●● ● ● ● ● ● 50 mtcars$hp ● 10 15 20 25 ● ● ● ● 30 mtcars$mpg 6 / 72 Axis Labels # xlab and ylab plot(mtcars$mpg, mtcars$hp, xlab = "miles per gallon", ylab = "horsepower") 250 ● ● ● ● ● ● 150 ● ● ● ●●● ●● ● ● ● ● ●● ● ● ● ● 50 horsepower ● 10 15 20 25 ● ● ● ● 30 miles per gallon 7 / 72 Title and subtitle # title and subtitle plot(mtcars$mpg, mtcars$hp, xlab = "miles per gallon", ylab = "horsepower", main = "Simple Scatterplot", sub = 'data matcars') Simple Scatterplot 250 ● ● ● ● ● ● 150 ● ● ● ●●● ●● ● ● ● ● ●● ● ● ● ● 50 horsepower ● 10 15 20 25 ● ● ● ● 30 miles per gallon data matcars 8 / 72 x and y coordinate ranges 250 ● ● ● ● ● ● ● 150 ● ● ● ●●● ●● ● ● ●● ● ● ● ● ● ● 50 mtcars$hp 350 # 'xlim' and 'ylim' plot(mtcars$mpg, mtcars$hp, xlim = c(10, 35), ylim = c(50, 400)) 10 15 20 25 ● ● 30 ● ● 35 mtcars$mpg 9 / 72 Type 250 150 50 mtcars$hp # using 'type' (e.g. lines) plot(mtcars$mpg, mtcars$hp, type = "l") 10 15 20 25 30 mtcars$mpg 10 / 72 Points # character expansion 'cex' # and 'point character' plot(mtcars$mpg, mtcars$hp, cex = 1.5, pch = 1) 250 ● ● ●● ● ● 150 ● ●● ●●● ●● ● ● ●● ● ● ● ● ● ● 50 mtcars$hp ● 10 15 20 25 ● ● ● ● 30 mtcars$mpg 11 / 72 Point symbols (pch) available in R ● 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ● ● 17 18 19 20 22 23 24 25 ● ● ● 16 ● 21 12 / 72 Point Character # 'pch' can be any character plot(mtcars$mpg, mtcars$hp, pch = "@") 250 @ @ @ @@ @ 150 @ @@ @@@ @ @ @@ @ @ @ @@ @ @ @ 50 mtcars$hp @ 10 15 20 25 @ @ @@ 30 mtcars$mpg 13 / 72 Point Character 250 ● 150 ● ● ● ● ● 50 mtcars$hp # 'pch' symbols will be recycled plot(mtcars$mpg, mtcars$hp, pch = 1:25) 10 15 20 25 ● ● 30 mtcars$mpg 14 / 72 Point Colors # color argument 'col' plot(mtcars$mpg, mtcars$hp, pch = 19, col = "blue", cex = 1.2) 250 ● ● ● ●● ● 150 ● ● ● ●●● ●● ● ● ● ● ●● ● ● ● ● 50 mtcars$hp ● 10 15 20 25 ● ● ● ● 30 mtcars$mpg 15 / 72 Coloring Point Symbols I I the col argument can be used to color symbols symbols 21 through 25 can additionally have their interiors filled by using the bg (background) argument 16 / 72 Coloring Point symbols ● 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ● ● 17 18 19 20 22 23 24 25 ● ● ● 16 ● 21 17 / 72 So far ... # using plot() plot(mtcars$mpg, mtcars$hp, xlim = c(10, 35), ylim = c(50, 400), xlab = "miles per gallon", ylab = "horsepower", main = "Simple Scatterplot", sub = 'data matcars', pch = 1:25, cex = 1.2, col = "blue") 18 / 72 100 150 200 250 300 350 400 ● ● ● ● ● ● 50 horsepower Simple Scatterplot 10 15 20 25 ● ● 30 35 miles per gallon data matcars 19 / 72 Low-Level Functions 20 / 72 High and Low level functions I I I Usually we call a high-level function Most times we change the default arguments Then we call low-level functions 21 / 72 Scatter plot # simple scatter-plot plot(mtcars$mpg, mtcars$hp) # adding text text(mtcars$mpg, mtcars$hp, labels = rownames(mtcars)) # dummy legend legend("topright", legend = "a legend") # graphic title title("Miles Per Galon -vs- Horsepower") 22 / 72 Miles Per Galon −vs− Horsepower ● Bora Maserati 300 a legend 200 150 ●Merc ● ● MercMerc 450SLC 450SE 450SL ● ●Firebird ● Dino Hornet Sportabout Pontiac Ferrari ●● Dodge AMC Challenger Javelin 100 ● 280 Merc●Merc 280C ● Lotus Europa ● ●4 Mazda RX4 Wag Mazda RX4 Drive Volvo 142E ● Hornet Valiant ●Corona ToyotaDatsun ● Merc ● 230 710 Porsche● 914−2 ●128●Corolla Toyota Fiat ●X1−9 Fiat Merc●240D Honda● Civic 50 mtcars$hp 250 ● Ford Pantera L ● Z28 ● 360 Duster Camaro Chrysler●Imperial ● Lincoln Continental ● Cadillac Fleetwood 10 15 20 25 30 mtcars$mpg 23 / 72 Scatter plot # simple scatter-plot plot(mtcars$mpg, mtcars$hp, type = "n", xlab = "miles per gallon", ylab = "horsepower") # grid lines abline(v = seq(from = 10, to = 30, by = 5), col = 'gray') abline(h = seq(from = 50, to = 300, by = 50), col = ' gray') # plot points points(mtcars$mpg, mtcars$hp, pch = 19, col = "blue") # plot text text(mtcars$mpg, mtcars$hp, labels = rownames(mtcars), pos = 4, col = "gray50") # graphic title title("Miles Per Galon -vs- Horsepower") 24 / 72 Miles Per Galon −vs− Horsepower Maserati Bora 200 ● Ford Pantera L ● Duster Camaro Z28 360 ● Chrysler Imperial Lincoln Continental Cadillac Fleetwood ● ● ● 150 ● ● Merc ●450SLC Merc Merc 450SE 450SL ● ●Hornet ●Pontiac Ferrari Sportabout Firebird Dino AMC Dodge Javelin Challenger ●● 100 ● ● Merc Merc 280C280 ● Lotus Europa Hornet142E RX4 4 Drive Wag Volvo Valiant ● ●Mazda ● Toyota Corona ● 230 ● Merc Datsun 710 ● Porsche 914−2 ● ● Fiat X1−9 ● Fiat ● 128 Toyota Corolla Merc 240D ● Honda Civic ● 50 horsepower 250 300 ● 10 15 20 25 30 miles per gallon 25 / 72 Test your knowledge The function plot() A) accepts any type of vector B) is a generic function C) works only for 1-D and 2-D objects D) is designed to display scatterplots and boxplots 26 / 72 Low-level functions Function points() lines() abline() segments() arrows() rect() polygon() text() symbols() legend() Description points connected line segments straight lines across a plot disconnected line segments arrows rectangles polygons text various symbols legends 27 / 72 Drawing Points with points() points(x, y, pch = int, col = str) I I pch integer or string indicating type of point character col color of points 28 / 72 # drawing points plot(mtcars$mpg, mtcars$hp, type = "n") points(mtcars$mpg, mtcars$hp) 250 ● ●● ● ● ● 150 ● ● ● ●●● ●● ● ● ● ● ●● ● ● ● ● 50 mtcars$hp ● 10 15 20 25 ● ● ● ● 30 mtcars$mpg 29 / 72 Connected Line Segments lines(x, y, lty = str, lwd = num, col = str) I I lty specifies the line texture. It should be one of "blank" (0), "solid" (1), "dashed"(2), "dotted" (3), "dotdash" (4), "longdash" (5) or "twodash" (6). lwd and col specify the line width and colour 30 / 72 250 150 50 mtcars$hp # connected lines plot(mtcars$mpg, mtcars$hp, type = "n") lines(mtcars$mpg, mtcars$hp, type = "s", lwd = 2) 10 15 20 25 30 mtcars$mpg 31 / 72 Line Graph Options The type argument can be used to produced other types of lines I type = "l" line graph I type = "s" step function (horizontal first) I type = "S" step function (vertical first) I type = "h" high density (needle) plot I type = "p" draw points I type = "b" draw points and lines I type = "o" over-plotting points and lines 32 / 72 Line Graph Options type = 'l' type = 's' type = 'S' type = 'h' 33 / 72 Connected Line Segments x <- 2005:2015 y <- c(81, 83, 84.3, 85, 85.4, 86.5, 88.3, 88.6, 90.8, 91.1, 91.3) plot(x, y, type = 'n', xlab = "Time", ylab = "Values") lines(x, y, lwd = 2) title(main = "Line Graph Example") 34 / 72 Connected Line Segments 86 84 82 Values 88 90 Line Graph Example 2006 2008 2010 2012 2014 Time 35 / 72 Drawing Straight Lines abline(a = intercept, b = slope) abline(h = numbers) abline(v = numbers) I I I The a / b form specifies a line in intercept / slope form h specifies horizontal lines at given y-values v specifies vartical lines at given x-values 36 / 72 # drawing straight lines plot(mtcars$mpg, mtcars$hp, type = "n") abline(v = seq(10, 30, by = 5), h = seq(50, 300, by = 50)) points(mtcars$mpg, mtcars$hp, pch = 19, col = "red") 250 ● ●● ● ● ● 150 ● ● ● ●●● ●● ● ● ● ● ●● ● ● ● ● 50 mtcars$hp ● 10 15 20 25 ● ● ● ● 30 mtcars$mpg 37 / 72 Drawing Disconnected Lines Disconnected lines can be drawn with the function: segments(x0, y0, x1, y1) I I The x0, y0, x1, y1 arguments give the start and end coordinates of the segments. Line texture, colour and width arguments can also be given. 38 / 72 Drawing Line Segments n <- 11 theta <- seq(0, 2 * pi, length = n + 1)[1:n] x <- sin(theta) y <- cos(theta) v1 <- rep(1:n, n) v2 <- rep(1:n, rep(n, n)) plot(x, y, type = 'n') segments(x[v1], y[v1], x[v2], y[v2]) 39 / 72 1.0 0.5 y 0.0 −0.5 −1.0 −1.0 −0.5 0.0 0.5 1.0 x 40 / 72 Drawing Polygons Polygons can be drawn with the function: polygon(x, y, col = str, border = str) I I I I x, y give the coordinates of the polygon vertexes. NA values separate polygons. col specifies the color of the interior. border specifies the color of the border. line texture and width specifications can also be given 41 / 72 Drawing Polygons 0.04 0.02 0.00 Density 0.06 Kernel Density Curve 10 20 30 40 N = 32 Bandwidth = 2.477 42 / 72 Adding Text We can add text using the function: text(x, y, labels, ...) I I I I I I x, y give the coordinates of the text. labels gives the actual text strings. font optional font for the text. col optional color for the text. srt rotation of the text. adj justification of the text. 43 / 72 Drawing Text plot(0.5, 0.5, xlim = c(0, 1), ylim = c(0, 1), type = 'n') abline(h = c(.2, .5, .8), v = c(.5, .2, .8), col = "lightgrey") text(0.5, 0.5, "srt = 45, adj = c(.5, .5)", srt = 45, adj = c(.5, .5)) text(0.5, 0.8, "adj = c(0, .5)", adj = c(0, .5)) text(0.5, 0.2, "adj = c(1, .5)", adj = c(1, .5)) text(0.2, 0.5, "adj = c(1, 1)", adj = c(1, 1)) text(0.8, 0.5, "adj = c(0, 0)", adj = c(0, 0)) 44 / 72 0.8 1.0 Drawing Text adj = c(0, 0) j= 0.5 c( .5 , 0.6 .5 ) adj = c(0, .5) t= adj = c(1, .5) 0.0 sr 0.4 0.2 45 , ad adj = c(1, 1) 0.0 0.2 0.4 0.6 0.8 1.0 0.5 45 / 72 Adding a Legend Legends can be added with: legend(xloc, lty = pch = xjust I I yloc, legend = text linetypes, lwd = linewidths, glyphname, col = colours, = justification, yjust = justification) xloc and yloc give the coordinates where the legend is to be placed xjust and yjust give the justification of the legend box with respect to the location. 46 / 72 Adding Legends # coords of exact line plot(mtcars$mpg, mtcars$hp) legend("topright", legend = "A legend") ● 300 A legend 200 ● ● 150 ● ● ● ●●● ●● 100 ● ● ●● ● ● ● ● ● ● 50 mtcars$hp 250 ● ● ● ● ● ● ● ● 10 15 20 25 30 mtcars$mpg 47 / 72 Plots from scratch 48 / 72 Customizing Annotations It is also possible to create a plot from scratch. Although this procedure is less documented, it is extremely flexible: 1. call plot.new() to start a new plot frame 2. call plot.window() to define coordinates 3. then call low-level functions: 4. typical options involve axis() 5. then title() (title, subtitle) 6. after that call other function: e.g. points(), lines(), etc 49 / 72 Plot from Scratch plot.new() plot.window(xlim = c(0, 10), ylim = c(-2, 4), xaxs = "i") axis(1, col.axis = "grey30") axis(2, col.axis = "grey30", las = 1) title(main = "Main Title", col.main = "tomato", sub = "Plot Subtitle", col.sub = "orange", xlab = "x-axis", ylab = "y-axis", col.lab = "blue", font.lab = 3) box("figure", col = "grey90") 50 / 72 Plot from Scratch Main Title 4 3 y−axis 2 1 0 −1 −2 0 2 4 6 8 10 x−axis Plot Subtitle 51 / 72 Another plot from scratch set.seed(5) x <- rnorm(200) y <- x + rnorm(200) plot.new() plot.window(xlim = c(-4.5, 4.5), xaxs = "i", ylim = c(-4.5, 4.5), yaxs = "i") z <- lm(y ~ x) abline(h = -4:4, v = -4:4, col = "lightgrey") abline(a = coef(z)[1], b = coef(z)[2], lwd = 2, col = "red") points(x, y) axis(1) axis(2, las = 1) box() title(main = "A Fitted Regression Line") 52 / 72 A Fitted Regression Line ●● 4 ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●●● ● ● ● ●●●● ●● ● ●●●● ● ● ● ● ● ● ●● ● ●● ● ● ●●● ● ● ●●●●●● ● ● ● ● ●● ● ●● ● ● ●● ● ●● ● ● ●● ● ● ●● ●● ● ●● ● ● ● ●● ● ● ● ●● ● ●● ● ● ● ● ●●●● ● ● ●● ●●● ● ●●●● ● ● ● ●● ● ● ●● ● ● ● ● ● ● ● ●● ●●●● ● ● ●●● ● ● ● ● ● ● ● ● ●● ●● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● 2 0 −2 ● ● ● ● ● ● −4 ● −4 −2 0 2 4 53 / 72 Creating a Plot from Scratch I Start a new plot with plot.new() I plot.new() opens a new (empty) plot frame I plot.new() chooses a default plotting region 54 / 72 Setting Up Coordinates Then use plot.window() to set up the coordinate system for the plotting frame # axis limits (0,1)x(0,1) plot.window(xlim = c(0, 1), ylim = c(0, 1)) By default plot.window() produces axis limits which are expanded by 6% over those actually specified. 55 / 72 Setting Up Coordinates The default limits expansion can be turned-off by specifying xaxs = "i" and/or yaxs = "i" plot.window(xlim, ylim, xaxs = "i") 56 / 72 Aspect Ratio Control Another important argument is asp, which allows us to specify the aspect ratio plot.window(xlim, ylim, xaxs = "i", asp = 1) asp = 1 means that unit steps in the x and y directions produce equal distances in the x and y directions on the plot. (Important to avoid distortion of circles that look like ellipses) 57 / 72 Drawing Axes The axis() function can be used to draw axes at any of the four sides of a plot. I side=1 below the graph I side=2 to the left of the graph I side=3 above the graph I side=4 to the right of the graph 58 / 72 Customizing Axes Axes can be customized via several arguments (see ?axis) I location of tick-marks I labels of axis I colors I sizes I text fonts I text orientation 59 / 72 Plot Annotation The function title() allows us to include labels in the margins I main main title above the graph I sub subtitle below the graph I xlab label for the x-axis I ylab label for the y-axis 60 / 72 Customizing Annotations The annotations can be customized with additional arguments for the fonts, colors, and size (expansion) I font.main, col.main, cex.main I font.sub, col.sub, cex.sub I font.lab, col.lab, cex.lab 61 / 72 Drawing Arrows Arrows can be drawn with the function: arrows(x0, y0, x1, y1, code = int, length = num, angle = num) I I I The x0, y0, x1, y1 arguments give the start and end coordinates. code=1 head at the start, code=2 head at the end, code=3 head at both ends length of the arrow head and angle to the shaft 62 / 72 Drawing Arrows plot.new() plot.window(xlim = c(0, 1), ylim = c(0, 1)) arrows(.05, .075, .45, .9, code = 1) arrows(.55, .9, .95, .075, code = 2) arrows(.1, 0, .9, 0, code = 3) text(.5, 1, "A", cex = 1.5) text(0, 0, "B", cex = 1.5) text(1, 0, "C", cex = 1.5) 63 / 72 Drawing Arrows A B C 64 / 72 Drawing Rectangles Rectangles can be drawn with the function: rect(x0, y0, x1, y1, col = str, border = str) I I I x0, y0, x1, y1 give the coordinates of diagonally opposite corners of the rectangles. col specifies the color of the interior. border specifies the color of the border. 65 / 72 Drawing Rectangles # barplot manually constructed plot.new() plot.window(xlim = c(0, 5), ylim = c(0, 10)) rect(0:4, 0, 1:5, c(7, 8, 4, 3), col = "turquoise", border = "white") axis(1) axis(2, las = 1) 66 / 72 Drawing Rectangles 10 8 6 4 2 0 0 1 2 3 4 5 67 / 72 Plot Regions 68 / 72 Anatomy of Plot Frame and Region Plot Region margin 4 margin 2 margin 3 margin 1 69 / 72 Adjusting the Margins Margins can be adjusted with the par() function in various ways: I In inches: par(mai = c(2, 2, 1, 1)) I In lines of text: par(mar = c(4, 4, 2, 2)) I Width and Height in inches: par(pin = c(5, 4)) 70 / 72 One more scatter plot # simple scatter-plot op <- par(mar = c(5, 4, 3, 1)) plot(mtcars$mpg, mtcars$hp, type = "n", xlab = "miles per gallon", ylab = "horsepower") # grid lines abline(v = seq(from = 10, to = 30, by = 5), col = 'gray') abline(h = seq(from = 50, to = 300, by = 50), col = ' gray') # points points(mtcars$mpg, mtcars$hp, pch = 19, col = "blue") # text (point labels) text(mtcars$mpg, mtcars$hp, labels = rownames(mtcars), pos = 4, col = "gray50") # title title("Miles Per Galon -vs- Horsepower") # reset graphical margins par(op) 71 / 72 Miles Per Galon −vs− Horsepower Maserati Bora 200 ● Ford Pantera L ● Duster Camaro Z28 360 ● Chrysler Imperial Lincoln Continental Cadillac Fleetwood ● ● ● 150 ● ● Merc ●450SLC Merc Merc 450SE 450SL ●● ● Hornet Pontiac Ferrari Sportabout Firebird Dino AMC Dodge Javelin Challenger ●● 100 ● ● Merc Merc 280C280 ● Lotus Europa Hornet142E RX4 4 Drive Wag Volvo Valiant ● ●Mazda ● Toyota Corona ● 230 ● Merc Datsun 710 ● Porsche 914−2 ● ● Fiat X1−9 Merc 240D ● 50 horsepower 250 300 ● ● 10 15 20 25 ● Fiat ● 128 Toyota Corolla Honda Civic 30 miles per gallon 72 / 72