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