Eric Hung
Eric Hung

Reputation: 522

Custom plot function using development version of plot.xts

I was building a custom function that automatically add legends to a plot.xts object.

Code here:

library(xts)
library(PerformanceAnalytics)
data(edhec)
R <- edhec[,1:4]
chartS <- function(R, 
                   y = NULL, 
                   multi.panel = FALSE, 
                   type = "l", 
                   yaxis.same = TRUE, 
                   event.lines = NULL, 
                   event.labels = NULL, 
                   event.col = 1,
                   event.offset = 1.2, 
                   event.pos = 2, 
                   event.srt = 90, 
                   event.cex = 1.5,
                   lty = 1,
                   lwd = 2,
                   legend.loc = NULL, 
                   legend.names = NULL, ...) {

  plot.xts(R, y = y, multi.panel = multi.panel, 
           type = type, yaxis.same = yaxis.same, lty = lty, lwd = lwd, ...)

  plot_object <- xts:::current.xts_chob()

  columns <- plot_object$Env$xdata
  columnnames <- plot_object$Env$column_names

  if(!is.null(event.lines)) {
    # error occurred
    addEventLines(xts(event.labels, as.Date(event.lines)), 
                  offset = event.offset, pos = event.pos, 
                  srt = event.srt, cex = event.cex, col = event.col, ...)
  }

  if(is.null(legend.loc))
    legend.loc <- "topright"  
  if(is.null(legend.names))
    legend.names <- columnnames

  if(!multi.panel)
    addLegend(legend.loc, legend.names, lty = lty, lwd = lwd, ...)
}


# chartS(R)
# chartS(R, lty = 1:4)
chartS(R, multi.panel = TRUE)

I failed to plot multiple windows with no messages when I set multi.panel = TRUE. But if I remove codes below plot.xts or move them to above plot.xts, it works again.

Remove codes below plot.xts

library(xts)
library(PerformanceAnalytics)
data(edhec)
R <- edhec[,1:4]
chartS <- function(R, 
                   y = NULL, 
                   multi.panel = FALSE, 
                   type = "l", 
                   yaxis.same = TRUE, 
                   event.lines = NULL, 
                   event.labels = NULL, 
                   event.col = 1,
                   event.offset = 1.2, 
                   event.pos = 2, 
                   event.srt = 90, 
                   event.cex = 1.5,
                   lty = 1,
                   lwd = 2,
                   legend.loc = NULL, 
                   legend.names = NULL, ...) {

  plot.xts(R, y = y, multi.panel = multi.panel, 
           type = type, yaxis.same = yaxis.same, lty = lty, lwd = lwd, ...)


}


# chartS(R)
# chartS(R, lty = 1:4)
chartS(R, multi.panel = TRUE)

Move codes to be above plot.xts

library(xts)
library(PerformanceAnalytics)
data(edhec)
R <- edhec[,1:4]
chartS <- function(R, 
                   y = NULL, 
                   multi.panel = FALSE, 
                   type = "l", 
                   yaxis.same = TRUE, 
                   event.lines = NULL, 
                   event.labels = NULL, 
                   event.col = 1,
                   event.offset = 1.2, 
                   event.pos = 2, 
                   event.srt = 90, 
                   event.cex = 1.5,
                   lty = 1,
                   lwd = 2,
                   legend.loc = NULL, 
                   legend.names = NULL, ...) {


  columns <- ncol(R)
  columnnames <- colnames(R)

  if(!is.null(event.lines)) {
    # error occurred
    addEventLines(xts(event.labels, as.Date(event.lines)), 
                  offset = event.offset, pos = event.pos, 
                  srt = event.srt, cex = event.cex, col = event.col, ...)
  }

  if(is.null(legend.loc))
    legend.loc <- "topright"  
  if(is.null(legend.names))
    legend.names <- columnnames

  if(!multi.panel)
    addLegend(legend.loc, legend.names, lty = lty, lwd = lwd, ...)

  plot.xts(R, y = y, multi.panel = multi.panel, 
           type = type, yaxis.same = yaxis.same, lty = lty, lwd = lwd, ...)
}


# chartS(R)
# chartS(R, lty = 1:4)
chartS(R, multi.panel = TRUE)

Any suggestions?

Upvotes: 0

Views: 172

Answers (1)

Joshua Ulrich
Joshua Ulrich

Reputation: 176718

You need to keep track of the plot object you're building, and return it so it auto-prints. You should also not access unexported objects (xts:::current.xts_chob()) because there's no guarantee they will remain consistent across versions.

chartS <-
function(R, y = NULL, multi.panel = FALSE, type = "l", yaxis.same = TRUE, 
         event.lines = NULL, event.labels = NULL, event.col = 1,
         event.offset = 1.2, event.pos = 2, event.srt = 90, event.cex = 1.5,
         lty = 1, lwd = 2, legend.loc = NULL, legend.names = NULL, ...)
{
  plot_object <- plot.xts(R, y = y, multi.panel = multi.panel, type = type,
    yaxis.same = yaxis.same, lty = lty, lwd = lwd, ...)

  columns <- plot_object$Env$xdata
  columnnames <- plot_object$Env$column_names

  if(!is.null(event.lines)) {
    plot_object <-
      addEventLines(xts(event.labels, as.Date(event.lines)), offset = event.offset,
        pos = event.pos, srt = event.srt, cex = event.cex, col = event.col, ...)
  }

  if(is.null(legend.loc))
    legend.loc <- "topright"  
  if(is.null(legend.names))
    legend.names <- columnnames

  if(!multi.panel)
    plot_object <- addLegend(legend.loc, legend.names, lty = lty, lwd = lwd, ...)

  return(plot_object)
}

Upvotes: 2

Related Questions