Search code examples
rplotglmnet

Adjusting top axis title and labels plots of plotmo::plot_glmnet in R


I use r package plotmo to visualize coefficient shrinkage of LASSO regression. By default, it add a top axis with title 'Degrees of Freedom'. How could I delete the top title or change the content of it? Generally, how could I adjust top axis (including title and axis labels) ploted by plotmo::plot_glmnet ?

library(glmnet)
library(plotmo) 
fit = glmnet(as.matrix(mtcars[-1]), mtcars[,1])
plot_glmnet(fit,xvar='lambda',label=7)

enter image description here

I've tried to use mtext and axis function, but it didn't work:

plot_glmnet(fit,xvar='lambda',label=7)
mtext('new top title', side=3)

enter image description here


Solution

  • There is a line in the code of plot_glmnet, mtext(toplabel...) that does this.. Unfortunately if you want to remove that, you have to create a new function with this line removed, and assign the namespace:

    new_plot_glmnet = function (x = stop("no 'x' argument"), xvar = c("rlambda", "lambda", 
        "norm", "dev"), label = 10, nresponse = NA, grid.col = NA, 
        s = NA, ...) 
    {
        check.classname(x, "x", c("glmnet", "multnet"))
        obj <- x
        beta <- get.beta(obj$beta, nresponse)
        ibeta <- nonzeroCoef(beta)
        if (length(ibeta) == 0) {
            plot(0:1, 0:1, col = 0)
            legend("topleft", legend = "all glmnet coefficients are zero", 
                bty = "n")
            return(invisible(NULL))
        }
        beta <- as.matrix(beta[ibeta, , drop = FALSE])
        xlim <- dota("xlim", ...)
        xvar <- match.arg1(xvar)
        switch(xvar, norm = {
            if (inherits(obj, "multnet") || inherits(obj, "mrelnet")) {
                stop0("xvar=\"norm\" is not supported by plot_gbm for ", 
                    "multiple responses (use plot.glmnet instead)")
            }
            x <- apply(abs(beta), 2, sum)
            if (!is.specified(xlim)) xlim <- c(min(x), max(x))
            xlab <- "L1 Norm"
            approx.f <- 1
        }, lambda = {
            x <- log(obj$lambda)
            if (!is.specified(xlim)) xlim <- c(min(x), max(x))
            xlab <- "Log Lambda"
            approx.f <- 0
        }, rlambda = {
            x <- log(obj$lambda)
            if (!is.specified(xlim)) xlim <- c(max(x), min(x))
            xlab <- "Log Lambda"
            approx.f <- 0
        }, dev = {
            x <- obj$dev.ratio
            if (!is.specified(xlim)) xlim <- c(min(x), max(x))
            xlab <- "Fraction Deviance Explained"
            approx.f <- 1
        })
        xlim <- fix.lim(xlim)
        if (xvar != "rlambda") 
            stopifnot(xlim[1] < xlim[2])
        else if (xlim[2] >= xlim[1]) 
            stop0("xlim[1] must be bigger than xlim[2] for xvar=\"rlambda\"")
        iname <- get.iname(beta, ibeta, label)
        old.par <- par("mar", "mgp", "cex.axis", "cex.lab")
        on.exit(par(mar = old.par$mar, mgp = old.par$mgp, cex.axis = old.par$cex.axis, 
            cex.lab = old.par$cex.lab))
        mar4 <- old.par$mar[4]
        if (length(iname)) {
            cex.names <- min(1, max(0.5, 2.5/sqrt(length(iname))))
            mar4 <- max(old.par$mar[4] + 1, 0.75 * cex.names * par("cex") * 
                max(nchar(names(iname))))
        }
        main <- dota("main", ...)
        nlines.needed.for.main <- if (is.specified(main)) 
            nlines(main) + 0.5
        else 0
        par(mar = c(old.par$mar[1], old.par$mar[2], max(old.par$mar[3], 
            nlines.needed.for.main + 2.6), mar4))
        par(mgp = c(1.5, 0.4, 0))
        par(cex.axis = 0.8)
        ylab <- "Coefficients"
        if (is.list(obj$beta)) 
            ylab <- paste0(ylab, ": Response ", rownames(obj$dfmat)[nresponse])
        coef.col <- get.coef.col(..., beta = beta)
        keep <- which((coef.col != "NA") & (coef.col != "0"))
        iname <- iname[iname %in% keep]
        beta[-keep, ] <- NA
        call.plot(graphics::matplot, force.x = x, force.y = t(beta), 
            force.main = "", force.col = coef.col, def.xlim = xlim, 
            def.xlab = xlab, def.ylab = ylab, def.lty = 1, def.lwd = 1, 
            def.type = "l", ...)
        abline(h = 0, col = "gray", lty = 3)
        maybe.grid(x = x, beta = beta, grid.col = grid.col, coef.col = coef.col, 
            ...)
        if (xvar == "rlambda") {
            annotate.rlambda(lambda = obj$lambda, x = x, beta = beta, 
                s = s, grid.col = grid.col, coef.col = coef.col, 
                ...)
            toplab <- "Lambda"
        }
        else {
            top.axis(obj, x, nresponse, approx.f)
            toplab <- "Degrees of Freedom"
        }
        #mtext(toplab, side = 3, line = 1.5, cex = par("cex") * par("cex.lab"))
        if (is.specified(main)) 
            mtext(main, side = 3, line = 3, , cex = par("cex"))
        if (length(iname)) 
            right.labs(beta, iname, cex.names, coef.col)
        invisible(NULL)
    }
    
    environment(new_plot_glmnet) <- asNamespace('plotmo')
    

    Then you plot:

    new_plot_glmnet(fit,xvar='lambda',label=7)
    mtext('new top title', side=3,padj=-2)
    

    enter image description here