edzer / hexbin

Hexagonal binning routines and plotting methods
37 stars 11 forks source link

Allow further graphical parameters in hexVP.loess #16

Closed daffp closed 3 years ago

daffp commented 3 years ago

Hi Edzer,

Following up re personal email on adding graphical parameters that can be passed to grid.lines in hexVP.loess function. Your request: "Can you propose a way that will not break user scripts that use col = 'color' argument?"

Below are a couple of suggestions that may be suitable (I have abbreviated the function calls for brevity but in each case gp would be passed to grid.lines):

library(grid)

f1a <- function (hbin, hvp = NULL, span = 0.4, col="red", n = 200, ...) {
      dots <- list(...)
      gp <- do.call(gpar, c(col=col, dots))
      return(gp)
}
f1a(); f1a(lwd=2, lty="dashed")
f1b <- function (hbin, hvp = NULL, span = 0.4, n = 200, ...) {
      dots <- list(...)
      if(is.null(dots$col)) dots$col <- "red" 
      gp <- do.call(gpar, dots)
      return(gp)

}

f1b(); f1b(lwd=2, lty="dashed")
f2 <- function (hbin, hvp = NULL, span = 0.4, col="red",  n = 200, gp=gpar()) {
    gp <- modifyList(gp, list(col=col))
    return(gp)
}
f2(); f2(gp=gpar(lwd=2, lty="dashed"))
f3 = function (hbin, hvp = NULL, span = 0.4, col="red", n = 200, gp=gpar()) {
    if(is.null(gp$col)) gp$col <- col
    return(gp)
}
f3(); f3(gp=gpar(lwd=2, lty="dashed"))

I think f1b() is perhaps most consistent with present code. Can document that all graphical parameters can be passed by name in the ellipses, it removes the explicit col= parameter and hopefully shouldn't break existing code. Let me know if any of these are suitable and I'll send a pull request.


A full example using f1b() would be

hexVP.loess_new <- function (hbin, hvp = NULL, span = 0.4, n = 200, ...) {
    dots <- list(...)
    if(is.null(dots$col)) dots$col <- "red" 
    gp <- do.call(gpar, dots)

    fit <- loess(hbin@ycm ~ hbin@xcm, weights = hbin@count, span = span)
    if (!is.null(hvp)) {
        pushHexport(hvp, clip = "on")
        grid.lines(seq(hbin@xbnds[1], hbin@xbnds[2], length = n), 
            predict(fit, seq(hbin@xbnds[1], hbin@xbnds[2], length = n)), 
            gp = gp, default.units = "native")
        popViewport()
    }
    invisible(fit)
  }

library(hexbin)
library(grid)

# Some data
d <- data.frame(x=rnorm(1000), y=rnorm(1000))
bin <- hexbin(d$x, d$y)

# old
p <- plot(bin)
hexVP.loess(bin, hvp = p$plot.vp, span = 0.4, col = "red", n = 200)

# new
p <- plot(bin)
hexVP.loess_new(bin, hvp = p$plot.vp, span = 0.4, n = 200)
hexVP.loess_new(bin, hvp = p$plot.vp, span = 0.4, col = "blue", lwd=3, lty="dashed", n = 200)