1\name{plot.zoo} 2\alias{plot.zoo} 3\alias{barplot.zoo} 4\alias{boxplot.zoo} 5\alias{lines.zoo} 6\alias{points.zoo} 7\title{Plotting zoo Objects} 8\description{ 9Plotting method for objects of class \code{"zoo"}. 10} 11\usage{ 12\method{plot}{zoo}(x, y = NULL, screens, plot.type, 13 panel = lines, xlab = "Index", ylab = NULL, main = NULL, 14 xlim = NULL, ylim = NULL, xy.labels = FALSE, xy.lines = NULL, 15 yax.flip = FALSE, oma = c(6, 0, 5, 0), 16 mar = c(0, 5.1, 0, if(yax.flip) 5.1 else 2.1), 17 col = 1, lty = 1, lwd = 1, pch = 1, type = "l", log = "", 18 nc, widths = 1, heights = 1, \dots) 19\method{lines}{zoo}(x, y = NULL, type = "l", \dots) 20\method{points}{zoo}(x, y = NULL, type = "p", \dots) 21} 22\arguments{ 23 \item{x}{an object of class \code{"zoo"}.} 24 \item{y}{an object of class \code{"zoo"}. If \code{y} is \code{NULL} 25 (the default) a time series plot of \code{x} is produced, otherwise 26 if both \code{x} and \code{y} are univariate \code{"zoo"} series, a 27 scatter plot of \code{y} versus \code{x} is produced.} 28 \item{screens}{factor (or coerced to factor) whose levels specify which 29 graph each series is to be plotted in. \code{screens=c(1,2,1)} 30 would plot series 1, 2 and 3 in graphs 1, 2 and 1. If not specified 31 then 1 is used if \code{plot.type="single"} and \code{seq_len(ncol(x))} 32 otherwise.} 33 \item{plot.type}{for multivariate zoo objects, "multiple" plots the 34 series on multiple plots and "single" superimposes them on a single 35 plot. Default is "single" if \code{screens} has only one level and 36 \code{"multiple"} otherwise. If neither \code{screens} nor 37 \code{plot.type} is specified then \code{"single"} 38 is used if there is one series and \code{"mulitple"} otherwise. This 39 option is provided for back compatibility. Usually \code{screens} is 40 used instead.} 41 \item{panel}{a \code{function(x, y, col, lty, \dots)} which gives the 42 action to be carried out in each panel of the display for 43 \code{plot.type = "multiple"}.} 44 \item{ylim}{if \code{plot.type = "multiple"} then it can be a list of 45 y axis limits. If not a list each graph has the same limits. 46 If any list element is not a pair then its range is used instead. If 47 \code{plot.type = "single"} then it is as in \code{plot}.} 48 \item{xy.labels}{logical, indicating if \code{\link{text}} labels should be 49 used in the scatter plot, or character, supplying a vector of labels to be used.} 50 \item{xy.lines}{logical, indicating if \code{\link{lines}} should be drawn in 51 the scatter plot. Defaults to the value of \code{xy.labels} if that is 52 logical, otherwise to \code{FALSE}.} 53 \item{yax.flip}{logical, indicating if the y-axis (ticks and numbering) 54 should flip from side 2 (left) to 4 (right) from series to series 55 when \code{type = "multiple"}.} 56 \item{xlab, ylab, main, xlim, oma, mar}{graphical arguments, see \code{\link{par}}.} 57 \item{col, lty, lwd, pch, type}{graphical arguments that can be vectors or 58 (named) lists. See the details for more information.} 59 \item{log}{specification of log scales as \code{"x"}, \code{"y"} or \code{"xy"}.} 60 \item{nc}{the number of columns to use when \code{plot.type = "multiple"}. 61 Defaults to \code{1} for up to \code{4} series, otherwise to \code{2}.} 62 \item{widths, heights}{widths and heights for individual graphs, see 63 \code{\link{layout}}.} 64 \item{\dots}{additional graphical arguments.} 65} 66 67\details{ 68The methods for \code{plot} and \code{lines} are very similar 69to the corresponding \code{ts} methods. However, the handling of 70several graphical parameters is more flexible for multivariate series. 71These parameters can be vectors of the same length as the number of 72series plotted or are recycled if shorter. They can also be (partially) 73named list, e.g., \code{list(A = c(1,2), c(3,4))} in which \code{c(3, 4)} 74is the default value and \code{c(1, 2)} the value only for series \code{A}. 75The \code{screens} argument can be specified in a similar way. 76If \code{plot.type} and \code{screens} conflict then multiple plots 77will be assumed. Also see the examples. 78 79In the case of a custom panel the panel can reference 80\code{parent.frame$panel.number} in order to determine which 81frame the panel is being called from. See examples. 82 83\code{par(mfrow=...)} and \code{Axis} can be used in conjunction with 84single panel plots in the same way as with other classic graphics. 85 86For multi-panel graphics, \code{plot.zoo} takes over the layout so 87\code{par(mfrow=...)} cannot be used. \code{Axis} can be used within 88the panels themselves but not outside the panel. See examples. 89Also, \code{par(new = TRUE)} is not supported for multi-panel graphics. 90 91In addition to classical time series line plots, there is also a 92simple \code{\link{barplot}} method for \code{"zoo"} series. Additionally, 93there is a \code{\link{boxplot}} method that visualizes the \code{coredata} 94of the \code{"zoo"} series with a box plot. 95} 96 97\seealso{\code{\link{zoo}}, \code{\link{plot.ts}}, \code{\link{barplot}}, 98\code{\link{boxplot}}, \code{\link{xyplot.zoo}}} 99 100\examples{ 101## example dates 102x.Date <- as.Date(paste(2003, 02, c(1, 3, 7, 9, 14), sep = "-")) 103 104## univariate plotting 105x <- zoo(rnorm(5), x.Date) 106x2 <- zoo(rnorm(5, sd = 0.2), x.Date) 107plot(x) 108lines(x2, col = 2) 109 110## multivariate plotting 111z <- cbind(x, x2, zoo(rnorm(5, sd = 0.5), x.Date)) 112plot(z, type = "b", pch = 1:3, col = 1:3, ylab = list(expression(mu), "b", "c")) 113colnames(z) <- LETTERS[1:3] 114plot(z, screens = 1, col = list(B = 2)) 115plot(z, type = "b", pch = 1:3, col = 1:3) 116plot(z, type = "b", pch = list(A = 1:5, B = 3), col = list(C = 4, 2)) 117plot(z, type = "b", screen = c(1,2,1), col = 1:3) 118# right axis is for broken lines 119plot(x) 120opar <- par(usr = c(par("usr")[1:2], range(x2))) 121lines(x2, lty = 2) 122# axis(4) 123axis(side = 4) 124par(opar) 125 126 127## Custom x axis labelling using a custom panel. 128# 1. test data 129z <- zoo(c(21, 34, 33, 41, 39, 38, 37, 28, 33, 40), 130 as.Date(c("1992-01-10", "1992-01-17", "1992-01-24", "1992-01-31", 131 "1992-02-07", "1992-02-14", "1992-02-21", "1992-02-28", "1992-03-06", 132 "1992-03-13"))) 133zz <- merge(a = z, b = z+10) 134# 2. axis tick for every point. Also every 3rd point labelled. 135my.panel <- function(x, y, ..., pf = parent.frame()) { 136 fmt <- "\%b-\%d" # format for axis labels 137 lines(x, y, ...) 138 # if bottom panel 139 if (with(pf, length(panel.number) == 0 || 140 panel.number \%\% nr == 0 || panel.number == nser)) { 141 # create ticks at x values and then label every third tick 142 axis(side = 1, at = x, labels = FALSE) 143 ix <- seq(1, length(x), 3) 144 labs <- format(x, fmt) 145 axis(side = 1, at = x[ix], labels = labs[ix], tcl = -0.7, cex.axis = 0.7) 146 } 147} 148# 3. plot 149plot(zz, panel = my.panel, xaxt = "n") 150 151# with a single panel plot a fancy x-axis is just the same 152# procedure as for the ordinary plot command 153plot(zz, screen = 1, col = 1:2, xaxt = "n") 154# axis(1, at = time(zz), labels = FALSE) 155tt <- time(zz) 156axis(side = 1, at = tt, labels = FALSE) 157ix <- seq(1, length(tt), 3) 158fmt <- "\%b-\%d" # format for axis labels 159labs <- format(tt, fmt) 160# axis(1, at = time(zz)[ix], labels = labs[ix], tcl = -0.7, cex.axis = 0.7) 161axis(side = 1, at = tt[ix], labels = labs[ix], tcl = -0.7, cex.axis = 0.7) 162legend("bottomright", colnames(zz), lty = 1, col = 1:2) 163 164## plot a mulitple ts series with nice x-axis using panel function 165tab <- ts(cbind(A = 1:24, B = 24:1), start = c(2006, 1), freq = 12) 166pnl.xaxis <- function(...) { 167 lines(...) 168 panel.number <- parent.frame()$panel.number 169 nser <- parent.frame()$nser 170 # if bottom panel 171 if (!length(panel.number) || panel.number == nser) { 172 tt <- list(...)[[1]] 173 ym <- as.yearmon(tt) 174 mon <- as.numeric(format(ym, "\%m")) 175 yy <- format(ym, "\%y") 176 mm <- substring(month.abb[mon], 1, 1) 177 if (any(mon == 1)) 178 # axis(1, tt[mon == 1], yy[mon == 1], cex.axis = 0.7) 179 axis(side = 1, at = tt[mon == 1], labels = yy[mon == 1], cex.axis = 0.7) 180 # axis(1, tt[mon > 1], mm[mon > 1], cex.axis = 0.5, tcl = -0.3) 181 axis(side = 1, at = tt[mon > 1], labels = mm[mon > 1], cex.axis = 0.5, tcl = -0.3) 182 } 183} 184plot(as.zoo(tab), panel = pnl.xaxis, xaxt = "n", main = "Fancy X Axis") 185 186## Another example with a custom axis 187# test data 188z <- zoo(matrix(1:25, 5), c(10,11,20,21)) 189colnames(z) <- letters[1:5] 190 191plot(zoo(coredata(z)), xaxt = "n", panel = function(x, y, ..., Time = time(z)) { 192 lines(x, y, ...) 193 # if bottom panel 194 pf <- parent.frame() 195 if (with(pf, panel.number \%\% nr == 0 || panel.number == nser)) { 196 axis(side = 1, at = x, labels = Time) 197 } 198}) 199 200 201## plot with left and right axes 202## modified from http://www.mayin.org/ajayshah/KB/R/html/g6.html 203suppressWarnings(RNGversion("3.5.0")) 204set.seed(1) 205z <- zoo(cbind(A = cumsum(rnorm(100)), B = cumsum(rnorm(100, mean = 0.2)))) 206opar <- par(mai = c(.8, .8, .2, .8)) 207plot(z[,1], type = "l", 208 xlab = "x-axis label", ylab = colnames(z)[1]) 209par(new = TRUE) 210plot(z[,2], type = "l", ann = FALSE, yaxt = "n", col = "blue") 211# axis(4) 212axis(side = 4) 213legend(x = "topleft", bty = "n", lty = c(1,1), col = c("black", "blue"), 214 legend = paste(colnames(z), c("(left scale)", "(right scale)"))) 215usr <- par("usr") 216# if you don't care about srt= in text then mtext is shorter: 217# mtext(colnames(z)[2], 4, 2, col = "blue") 218text(usr[2] + .1 * diff(usr[1:2]), mean(usr[3:4]), colnames(z)[2], 219 srt = -90, xpd = TRUE, col = "blue") 220par(opar) 221 222 223## another plot with left and right axes 224## modified from https://stat.ethz.ch/pipermail/r-help/2014-May/375293.html 225d1 <- c(38.2, 18.1, 83.2, 42.7, 22.8, 48.1, 81.8, 129.6, 52.0, 110.3) 226d2 <- c(2.2, 0.8, 0.7, 1.6, 0.9, 0.9, 1.1, 2.8, 5.1, 2.1) 227z1 <- zooreg(d1, start = as.POSIXct("2013-01-01 00:00:01"), frequency = 0.0000006) 228z2 <- zooreg(d2, start = as.POSIXct("2013-01-01 00:00:20"), frequency = 0.0000006) 229zt <- zooreg(rnorm(1050), start = as.POSIXct("2013-01-01 00:00:01"), frequency = 0.00007) 230z <- merge(zt, z1, z2, all = TRUE) 231z <- na.spline(z[,2:3], na.rm = FALSE) 232## function to round up to a number divisible by n (2011 by Owen Jones) 233roundup <- function(x, n) ceiling(ceiling(x)/n) * n 234## plot how to match secondary y-axis ticks to primary ones 235plot(z$z1, ylim = c(0, signif(max(na.omit(z$z1)), 2)), xlab = "") 236## use multiplication for even tick numbers and fake sekondary y-axis 237max.yl <- roundup(max(na.omit(z$z2)), par("yaxp")[3]) 238multipl.yl <- max(na.omit(z$z2)) / max.yl 239multipl.z2 <- signif(max(na.omit(z$z1) * 1.05), 2)/max.yl 240lines(z$z2 * multipl.z2, lty = 2) 241at4 <- axTicks(4) 242axis(4, at = at4, seq(0, max.yl, length.out = par("yaxp")[3] + 1)) 243 244 245# automatically placed point labels 246\dontrun{ 247library("maptools") 248pointLabel(time(z), coredata(z[,2]), labels = format(time(z)), cex = 0.5) 249} 250 251## plot one zoo series against the other. 252plot(x, x2) 253plot(x, x2, xy.labels = TRUE) 254plot(x, x2, xy.labels = 1:5, xy.lines = FALSE) 255 256## shade a portion of a plot and make axis fancier 257 258v <- zooreg(rnorm(50), start = as.yearmon(2004), freq = 12) 259 260plot(v, type = "n") 261u <- par("usr") 262rect(as.yearmon("2007-8"), u[3], as.yearmon("2009-11"), u[4], 263 border = 0, col = "grey") 264lines(v) 265axis(1, floor(time(v)), labels = FALSE, tcl = -1) 266 267## shade certain times to show recessions, etc. 268v <- zooreg(rnorm(50), start = as.yearmon(2004), freq = 12) 269plot(v, type = "n") 270u <- par("usr") 271rect(as.yearmon("2007-8"), u[3], as.yearmon("2009-11"), u[4], 272 border = 0, col = "grey") 273lines(v) 274axis(1, floor(time(v)), labels = FALSE, tcl = -1) 275 276## fill area under plot 277 278pnl.xyarea <- function(x, y, fill.base = 0, col = 1, ...) { 279 lines(x, y, ...) 280 panel.number <- parent.frame()$panel.number 281 col <- rep(col, length = panel.number)[panel.number] 282 polygon(c(x[1], x, tail(x, 1), x[1]), 283 c(fill.base, as.numeric(y), fill.base, fill.base), col = col) 284} 285plot(zoo(EuStockMarkets), col = rainbow(4), panel = pnl.xyarea) 286 287 288## barplot 289x <- zoo(cbind(rpois(5, 2), rpois(5, 3)), x.Date) 290barplot(x, beside = TRUE) 291 292## boxplot 293boxplot(x) 294 295## 3d plot 296## The persp function in R (not part of zoo) works with zoo objects. 297## The following example is by Enrico Schumann. 298## https://stat.ethz.ch/pipermail/r-sig-finance/2009q1/003710.html 299nC <- 10 # columns 300nO <- 100 # observations 301dataM <- array(runif(nC * nO), dim=c(nO, nC)) 302zz <- zoo(dataM, 1:nO) 303persp(1:nO, 1:nC, zz) 304 305# interactive plotting 306\dontrun{ 307library("TeachingDemos") 308tke.test1 <- list(Parameters = list( 309 lwd = list("spinbox", init = 1, from = 0, to = 5, increment = 1, width = 5), 310 lty = list("spinbox", init = 1, from = 0, to = 6, increment = 1, width = 5) 311)) 312z <- zoo(rnorm(25)) 313tkexamp(plot(z), tke.test1, plotloc = "top") 314} 315 316# setting ylim on a multi-panel plot - 2nd panel y axis range is 1-50 317data("anscombe", package = "datasets") 318ans6 <- zoo(anscombe[, 1:6]) 319screens <- c(1, 1, 2, 2, 3, 3) 320ylim <- unname(tapply(as.list(ans6), screens, range)) 321ylim[[2]] <- 1:50 # or ylim[[2]] <- c(1, 50) 322plot(ans6, screens = screens, ylim = ylim) 323 324} 325\keyword{ts} 326