Question

I would like to do a graph in R using our company colors. This means the background of all charts should be a light blue, the plotting region however should be white. I was searching for answers and found that drawing a rect does the job (almost). However the plotting region is now white and the graph not visible anymore. Is this even possible?

getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)

GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_ORANGE<-rgb(243/255, 112/255, 33/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)

par(bg=GRAPH_BACKGROUND)

colorPlottingBackground<-function(PlottingBackgroundColor = "white"){
  rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], col ="white")
}

plot.xts(SPY, col=GRAPH_BLUE)
colorPlottingBackground()
Was it helpful?

Solution 2

The issue is that you plot your white rectangle after plotting your data, therefore overwriting them. Since plot.xts doesn't have an argument add that would allow you to call it after drawing the rectangle, the only solution I see would be to modify function plot.xts.

plot.xtsMODIFIED<-function (x, y = NULL, type = "l", auto.grid = TRUE, major.ticks = "auto", 
    minor.ticks = TRUE, major.format = TRUE, bar.col = "grey", 
    candle.col = "white", ann = TRUE, axes = TRUE, ...) 
{
    series.title <- deparse(substitute(x))
    ep <- axTicksByTime(x, major.ticks, format.labels = major.format)
    otype <- type
    if (is.OHLC(x) && type %in% c("candles", "bars")) {
        x <- x[, has.OHLC(x, TRUE)]
        xycoords <- list(x = .index(x), y = seq(min(x), max(x), 
            length.out = NROW(x)))
        type <- "n"
    }
    else {
        if (NCOL(x) > 1) 
            warning("only the univariate series will be plotted")
        if (is.null(y)) 
            xycoords <- xy.coords(.index(x), x[, 1])
    }
    ###The next three lines are the only modifications i made to the function####
    plot(xycoords$x, xycoords$y, type = "n", axes = FALSE, ann = FALSE) 
    rect(par("usr")[1], par("usr")[3], par("usr")[2], par("usr")[4], col ="white")
    if(type=="l"){lines(xycoords$x, xycoords$y, ...)}

    if (auto.grid) {
        abline(v = xycoords$x[ep], col = "grey", lty = 4)
        grid(NA, NULL)
    }
    if (is.OHLC(x) && otype == "candles") 
        plot.ohlc.candles(x, bar.col = bar.col, candle.col = candle.col, 
            ...)
    dots <- list(...)
    if (axes) {
        if (minor.ticks) 
            axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB", 
                ...)
        axis(1, at = xycoords$x[ep], labels = names(ep), las = 1, 
            lwd = 1, mgp = c(3, 2, 0), ...)
        axis(2, ...)
    }
    box()
    if (!"main" %in% names(dots)) 
        title(main = series.title)
    do.call("title", list(...))
    assign(".plot.xts", recordPlot(), .GlobalEnv)
}

Then your script become:

library(quantmod)
getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)

GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)

par(bg=GRAPH_BACKGROUND)

plot.xtsMODIFIED(SPY, col=GRAPH_BLUE)

enter image description here

The error you're getting (Error in axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB", ...) : formal argument "col" matched by multiple actual arguments.) was also thrown with your previous script. It has to do with the fact that plot.xts uses several time argument ... and that argument col is both valid for axis and plot(or here in my modified version, lines). If you want to avoid it, i see two solutions: Either you want your axis to be of the same color as your line and therefore you have to change the line that says:

...
axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB", 
            ...)
...

Into

...
axis(1, at = xycoords$x, labels = FALSE, ...)
...

Or you want the axis to have the color intended by the writer of the original plot.xts in which case you need to differenciate the color of the lines and that of the axis.

 plot.xtsMODIFIED<-function (x, y = NULL, type = "l", auto.grid = TRUE, major.ticks = "auto", 
                             minor.ticks = TRUE, major.format = TRUE, bar.col = "grey", 
                             candle.col = "white", ann = TRUE, axes = TRUE, 
                             lcol, ...) 
{
...
if(type=="l"){lines(xycoords$x, xycoords$y, lcol, ...)}
...
}

And then in your actual call:

plot.xtsMODIFIED(SPY, lcol=GRAPH_BLUE)

OTHER TIPS

I know you already accepted @plannapus's answer, but this is a much simpler solution

par(bg="lightblue")
plot(0, 0, type="n", ann=FALSE, axes=FALSE)
u <- par("usr") # The coordinates of the plot area
rect(u[1], u[3], u[2], u[4], col="white", border=NA)

par(new=TRUE)
plot(1:10, cumsum(rnorm(10)))

What you basically do is to overlay two plots using par(new=TRUE): one with only a white rectangle; and another one with the contents you actually want to plot.

enter image description here

plot.xts will accept the panel.first argument, which is another way to draw the rectangle before plotting the line.

library(quantmod)
getSymbols('SPY', from='1998-01-01', to='2011-07-31', adjust=T)

GRAPH_BLUE<-rgb(43/255, 71/255,153/255)
GRAPH_BACKGROUND<-rgb(180/255, 226/255, 244/255)
par(bg=GRAPH_BACKGROUND)
white.rect=function() do.call(rect,as.list(c(par()$usr[c(1,3,2,4)],col="white")))
plot.xts(SPY,panel.first=white.rect())

This does not address the issue with col=GRAPH_BLUE pointed out by @plannapus.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top