diff --git a/.Rbuildignore b/.Rbuildignore index 799cd3c..74da3e1 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -23,3 +23,6 @@ ^_pkgdown\.yml$ ^manuscript$ ^rda/scott/$ +^appveyor\.yml$ +^CRAN-RELEASE$ +^cran-comments\.md$ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 24aa0a3..0343527 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -21,5 +21,5 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be repor opening an issue or contacting one or more of the project maintainers. This Code of Conduct is adapted from the Contributor Covenant -(http://contributor-covenant.org), version 1.0.0, available at -http://contributor-covenant.org/version/1/0/0/ +(https://www.contributor-covenant.org), version 1.0.0, available at +https://contributor-covenant.org/version/1/0/0/. diff --git a/CRAN-RELEASE b/CRAN-RELEASE new file mode 100644 index 0000000..7ee7d9f --- /dev/null +++ b/CRAN-RELEASE @@ -0,0 +1,2 @@ +This package was submitted to CRAN on 2019-12-02. +Once it is accepted, delete this file and tag the release (commit 357d86d705). diff --git a/DESCRIPTION b/DESCRIPTION index d192cd2..d994e3e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: sail Title: Sparse Additive Interaction Learning -Version: 0.0.0.9000 +Version: 0.1.0 Authors@R: c( person("Sahir", "Bhatnagar", email = "sahir.bhatnagar@gmail.com", role = c("aut", "cre"), comment = "http://sahirbhatnagar.com/"), @@ -9,10 +9,12 @@ Authors@R: c( person("Celia", "Greenwood", email = "celia.greenwood@mcgill.ca", role = c("aut"), comment = "https://www.mcgill.ca/statisticalgenetics/") ) -Description: Sparse Additive Interaction Learning with the strong heredity property, i.e., +Description: Sparse additive interaction learning with the strong heredity property, i.e., an interaction is selected only if its corresponding main effects are also included. Fits a linear model with non-linear interactions via penalized maximum likelihood. - Interactions are limited to a single exposure or environment variable. + Interactions are limited to a single exposure or environment variable. For more information, + see the website below and the accompanying paper: Bhatnagar et al., "A sparse additive model for + high-dimensional interactions with an exposure variable", 2019, . Depends: R (>= 3.4.0) Imports: glmnet, @@ -22,7 +24,7 @@ Suggests: grpreg, truncnorm, foreach, - doMC, + doParallel, testthat, covr, vdiffr, @@ -32,6 +34,6 @@ License: MIT + file LICENSE Encoding: UTF-8 LazyData: true BugReports: https://github.com/sahirbhatnagar/sail/issues -URL: https://github.com/sahirbhatnagar/sail -RoxygenNote: 6.0.1 +URL: https://sahirbhatnagar.com/sail +RoxygenNote: 6.1.1 VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 1d81c74..0ff2fa9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,27 +1,27 @@ -# Generated by roxygen2: do not edit by hand - -S3method(coef,cv.sail) -S3method(coef,sail) -S3method(plot,cv.sail) -S3method(plot,sail) -S3method(predict,cv.sail) -S3method(predict,sail) -S3method(print,sail) -export(cv.sail) -export(gendata) -export(plotInter) -export(plotMain) -export(sail) -importFrom(grDevices,hcl) -importFrom(graphics,abline) -importFrom(graphics,axis) -importFrom(graphics,legend) -importFrom(graphics,lines) -importFrom(graphics,mtext) -importFrom(graphics,par) -importFrom(graphics,plot.default) -importFrom(graphics,segments) -importFrom(graphics,text) -importFrom(stats,approx) -importFrom(stats,coef) -importFrom(stats,predict) +# Generated by roxygen2: do not edit by hand + +S3method(coef,cv.sail) +S3method(coef,sail) +S3method(plot,cv.sail) +S3method(plot,sail) +S3method(predict,cv.sail) +S3method(predict,sail) +S3method(print,sail) +export(cv.sail) +export(gendata) +export(plotInter) +export(plotMain) +export(sail) +importFrom(grDevices,hcl) +importFrom(graphics,abline) +importFrom(graphics,axis) +importFrom(graphics,legend) +importFrom(graphics,lines) +importFrom(graphics,mtext) +importFrom(graphics,par) +importFrom(graphics,plot.default) +importFrom(graphics,segments) +importFrom(graphics,text) +importFrom(stats,approx) +importFrom(stats,coef) +importFrom(stats,predict) diff --git a/R/cv.sail.R b/R/cv.sail.R index 0bc66b0..447eb94 100644 --- a/R/cv.sail.R +++ b/R/cv.sail.R @@ -33,7 +33,7 @@ #' Default: FALSE #' @param parallel If \code{TRUE}, use parallel \code{foreach} to fit each fold. #' Must register parallel before hand using the -#' \code{\link[doMC]{registerDoMC}} function from the \code{doMC} package. See +#' \code{\link[doParallel]{registerDoParallel}} function from the \code{doParallel} package. See #' the example below for details. Default: FALSE #' @return an object of class \code{"cv.sail"} is returned, which is a list with #' the ingredients of the cross-validation fit. \describe{ \item{lambda}{the @@ -80,23 +80,19 @@ #' models with the strong heredity property (2018+). Preprint. #' @seealso \code{\link[splines]{bs}} \code{\link{sail}} #' @examples -#' \dontrun{ -#' if(interactive()){ -#' f.basis <- function(i) splines::bs(i, degree = 5) +#' f.basis <- function(i) splines::bs(i, degree = 3) #' data("sailsim") -#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nfolds = 10) -#' #' # Parallel -#' library(doMC) -#' registerDoMC(cores = 4) +#' library(doParallel) +#' cl <- makeCluster(2) +#' registerDoParallel(cl) #' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' parallel = TRUE, nlambda = 100, nfolds = 10) +#' parallel = TRUE, nlambda = 10, +#' maxit = 25, basis = f.basis, +#' nfolds = 3, dfmax = 5) +#' stopCluster(cl) #' # plot cross validated curve #' plot(cvfit) -#' # plot solution path -#' plot(cvfit$sail.fit) -#' #' # solution at lambda.min #' coef(cvfit, s = "lambda.min") #' # solution at lambda.1se @@ -104,18 +100,7 @@ #' # non-zero coefficients at lambda.min #' predict(cvfit, s = "lambda.min", type = "nonzero") #' -#' # predicted response -#' predict(cvfit, s = "lambda.min") -#' predict(cvfit, s = "lambda.1se") -#' # predict response at any value for lambda -#' predict(cvfit, s = 0.457) #' -#' # predict response for new data set -#' newx <- sailsim$x * 1.10 -#' newe <- sailsim$e * 2 -#' predict(cvfit, newx = newx, newe = newe, s = "lambda.min") -#' } -#' } #' @rdname cv.sail #' @export cv.sail <- function(x, y, e, ..., @@ -259,7 +244,7 @@ cv.sail <- function(x, y, e, ..., #' @return A vector of CV fold ID's for each observation in \code{y} #' @details For numeric y, the sample is split into groups sections based on #' percentiles and sampling is done within these subgroups -#' @references \url{http://topepo.github.io/caret/splitting.html} +#' @references \url{https://topepo.github.io/caret/data-splitting.html} createfolds <- function(y, k = 10, list = FALSE, returnTrain = FALSE) { if (class(y)[1] == "Surv") { y <- y[, "time"] @@ -335,7 +320,7 @@ createfolds <- function(y, k = 10, list = FALSE, returnTrain = FALSE) { #' @rdname cv.lspath #' @seealso \code{\link{cv.sail}} #' @details The output of the \code{cv.lspath} function only returns values for -#' those tuning paramters that converged. \code{cvcompute, getmin, +#' those tuning parameters that converged. \code{cvcompute, getmin, #' lambda.interp} are taken verbatim from the \code{glmnet} package #' @references Jerome Friedman, Trevor Hastie, Robert Tibshirani (2010). #' Regularization Paths for Generalized Linear Models via Coordinate Descent. diff --git a/R/kkt.R b/R/kkt.R index 5e750b7..f5686be 100644 --- a/R/kkt.R +++ b/R/kkt.R @@ -121,12 +121,12 @@ KKT <- function(b0, betaE, beta, gamma, alpha, y, phij, xe_phij, e, df, for (l in 1:length(lambda)) { if (abs(B0[l, ]) > thr) { - cat("violate at b0 ", B0[l, ], " lambda=", lambda[l], "\n") + warning("violate at b0 ", B0[l, ], " lambda=", lambda[l], "\n") ctr <- ctr + 1 } } - cat("% of violations for beta0", ctr / length(lambda), "\n") + warning("% of violations for beta0", ctr / length(lambda), "\n") # KKT for betaE ----------------------------------------------------------- @@ -147,19 +147,19 @@ KKT <- function(b0, betaE, beta, gamma, alpha, y, phij, xe_phij, e, df, if (betaE[l] == 0) { BE <- dl_norm_betaE / (-lambda[l] * (1 - lambda2) * we) if (abs(BE) > 1 + thr) { - cat("violate at bE = 0", abs(BE), " lambda=", lambda[l], "\n") + warning("violate at bE = 0", abs(BE), " lambda=", lambda[l], "\n") ctr <- ctr + 1 } } else { BE <- as.vector(dl_norm_betaE + lambda[l] * (1 - lambda2) * we * sign(betaE[l])) if (abs(BE) > thr) { - cat("violate at bE != 0", abs(BE), " lambda=", lambda[l], "\n") + warning("violate at bE != 0", abs(BE), " lambda=", lambda[l], "\n") ctr <- ctr + 1 - } # else {cat("no violation at bE != 0", BE, " lambda=",lambda[l], "\n")} + } # else {warning("no violation at bE != 0", BE, " lambda=",lambda[l], "\n")} } } - cat("% of violations for betaE", ctr / length(lambda), "\n") + warning("% of violations for betaE", ctr / length(lambda), "\n") # return(list(v = ctr/length(lambda))) # browser() @@ -181,20 +181,20 @@ KKT <- function(b0, betaE, beta, gamma, alpha, y, phij, xe_phij, e, df, if (gamma[g, l] == 0) { BE <- dl_norm_gammaj / (-lambda[l] * (1 - lambda2) * we) if (abs(BE) > 1 + thr) { - cat("violate at gamma_j = 0", BE, " lambda=", lambda[l], "\n") + warning("violate at gamma_j = 0", BE, " lambda=", lambda[l], "\n") ctr <- ctr + 1 } } else { BE <- as.vector(dl_norm_gammaj + lambda[l] * (1 - lambda2) * we * sign(gamma[g, l])) if (abs(BE) > thr) { - cat("violate at gamma_j != 0", BE, " lambda=", lambda[l], "\n") + warning("violate at gamma_j != 0", BE, " lambda=", lambda[l], "\n") ctr <- ctr + 1 - } # else {cat("no violation at bE != 0", BE, " lambda=",lambda[l], "\n")} + } # else {warning("no violation at bE != 0", BE, " lambda=",lambda[l], "\n")} } } } - cat("% of violations for gamma", ctr / length(lambda), "\n") + warning("% of violations for gamma", ctr / length(lambda), "\n") @@ -223,22 +223,22 @@ KKT <- function(b0, betaE, beta, gamma, alpha, y, phij, xe_phij, e, df, if (b_norm != 0) { AA <- dl_prod + beta[ind, l] * lambda[l] * (1 - lambda2) * wj[g] / b_norm - # cat(AA,"\n") + # warning(AA,"\n") if (sum(abs(AA)) >= thr) { - cat("violate at bX != 0", sum(abs(AA)), " lambda=", lambda[l], "\n") + warning("violate at bX != 0", sum(abs(AA)), " lambda=", lambda[l], "\n") ctr <- ctr + 1 } } else { BB <- dl_norm - lambda[l] * (1 - lambda2) * wj[g] - # cat(BB,"\n") + # warning(BB,"\n") if (BB > thr) { - cat("violate at bX = 0", BB, " lambda=", lambda[l], "\n") + warning("violate at bX = 0", BB, " lambda=", lambda[l], "\n") ctr <- ctr + 1 } } } } - cat("% of violations for bTheta", ctr / length(lambda), "\n") + warning("% of violations for bTheta", ctr / length(lambda), "\n") return(ctr / length(lambda)) } # nocov end diff --git a/R/methods.R b/R/methods.R index da57026..80a1778 100644 --- a/R/methods.R +++ b/R/methods.R @@ -43,9 +43,9 @@ #' and right lambda indices. \code{coef(...)} is equivalent to #' \code{predict(sail.object, type="coefficients",...)} #' @examples -#' f.basis <- function(i) splines::bs(i, degree = 5) +#' f.basis <- function(i) splines::bs(i, degree = 3) #' fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis, dfmax = 10) +#' basis = f.basis, dfmax = 5, nlambda = 10, maxit = 20) #' predict(fit) # predicted response for whole solution path #' predict(fit, s = 0.45) # predicted response for a single lambda value #' predict(fit, s = c(2.15, 0.32, 0.40), type="nonzero") # nonzero coefficients @@ -138,18 +138,26 @@ coef.sail <- function(object, s = NULL, ...) { #' @details This function makes it easier to use the results of cross-validation #' to make a prediction. #' @examples -#' \dontrun{ -#' if(interactive()){ #' data("sailsim") #' f.basis <- function(i) splines::bs(i, degree = 3) -#' cvfit <- cv.sail(x = sailsim$x[,1:20,drop=F], y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nfolds = 10) +#' library(doParallel) +#' cl <- makeCluster(2) +#' registerDoParallel(cl) +#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, +#' parallel = TRUE, nlambda = 10, +#' maxit = 20, basis = f.basis, +#' nfolds = 3, dfmax = 5) +#' stopCluster(cl) #' predict(cvfit) # predict at "lambda.1se" #' predict(cvfit, s = "lambda.min") # predict at "lambda.min" #' predict(cvfit, s = 0.5) # predict at specific value of lambda #' predict(cvfit, type = "nonzero") # non-zero coefficients at lambda.1se -#' } -#' } +#' +#' # predict response for new data set +#' newx <- sailsim$x * 1.10 +#' newe <- sailsim$e * 2 +#' predict(cvfit, newx = newx, newe = newe, s = "lambda.min") +#' #' @rdname predict.cv.sail #' @seealso \code{\link{predict.sail}} #' @export @@ -202,15 +210,12 @@ coef.cv.sail <- function(object, s = c("lambda.1se", "lambda.min"), ...) { #' percent deviance explained (relative to the null deviance). For #' \code{type="gaussian"} this is the r-squared. #' @examples -#' \dontrun{ -#' if(interactive()){ #' data("sailsim") #' f.basis <- function(i) splines::bs(i, degree = 3) #' fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis) +#' basis = f.basis, dfmax = 5, nlambda = 10, +#' maxit = 20) #' fit -#' } -#' } #' @rdname print.sail #' @seealso \code{\link{sail}}, \code{\link{cv.sail}} #' @export @@ -241,20 +246,16 @@ print.sail <- function(x, digits = max(3, getOption("digits") - 3), ...) { #' @details A coefficient profile plot is produced #' @return A plot is produced and nothing is returned #' @examples -#' \dontrun{ -#' if(interactive()){ #' data("sailsim") #' f.basis <- function(i) splines::bs(i, degree = 3) -#' fit <- sail(x = sailsim$x[,1:10,drop=F], y = sailsim$y, e = sailsim$e, -#' basis = f.basis) +#' fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, +#' basis = f.basis, dfmax = 10, nlambda = 10, maxit = 100) #' plot(fit) -#' } -#' } #' @rdname plot.sail #' @seealso \code{\link{sail}}, \code{\link{cv.sail}} #' @export plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { - op <- graphics::par(no.readonly = TRUE) + # op <- graphics::par(no.readonly = TRUE) type <- match.arg(type) @@ -267,7 +268,9 @@ plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { if (type == "main") { - graphics::par(mar = 0.1 + c(4, 5, 2.5, 1)) + oldpar <- par(mar = 0.1 + c(4, 5, 2.5, 1)) + on.exit(par(oldpar)) + plotSailCoef( coefs = x$beta, environ = x$bE, @@ -282,7 +285,9 @@ plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { } if (type == "interaction") { - graphics::par(mar = 0.1 + c(4, 5, 2.5, 1)) + oldpar <- par(mar = 0.1 + c(4, 5, 2.5, 1)) + on.exit(par(oldpar)) + plotSailCoef( coefs = x$alpha, lambda = x$lambda, @@ -305,11 +310,14 @@ plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { # cex.main = 1.2 # ) + oldpar <- par("mfrow", "tcl", "family", "omi", + "cex.lab", "font.lab", "cex.axis", + "cex.main", "mar") + on.exit(par(oldpar)) + par(mfrow=c(2,1), tcl=-0.5, family="serif", omi=c(0.2,0.2,0,0), cex.lab = 1.2, font.lab = 1.2, cex.axis = 1.2, - cex.main = 1.2) - - par(mar=c(2,4,2,3.2)) + cex.main = 1.2, mar=c(2,4,2,3.2)) plotSailCoef( coefs = x$beta, environ = x$bE, @@ -337,7 +345,7 @@ plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { } - graphics::par(op) + # graphics::par(op) } @@ -353,15 +361,17 @@ plot.sail <- function(x, type = c("both", "main", "interaction"), ...) { #' @return A plot is produced and nothing is returned #' @details This is a port of \code{plot.cv.glmnet} #' @examples -#' \dontrun{ -#' if(interactive()){ #' data("sailsim") #' f.basis <- function(i) splines::bs(i, degree = 3) -#' cvfit <- cv.sail(x = sailsim$x[,1:10,drop=F], y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nfolds = 10) +#' library(doParallel) +#' cl <- makeCluster(2) +#' registerDoParallel(cl) +#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, +#' parallel = TRUE, nlambda = 10, +#' maxit = 100, basis = f.basis, +#' nfolds = 3, dfmax = 10) +#' stopCluster(cl) #' plot(cvfit) -#' } -#' } #' @rdname plot.cv.sail #' @seealso \code{\link{sail}}, \code{\link{cv.sail}} #' @references Jerome Friedman, Trevor Hastie, Robert Tibshirani (2010). diff --git a/R/plot.R b/R/plot.R index 6d867d6..80ddcdc 100644 --- a/R/plot.R +++ b/R/plot.R @@ -1,466 +1,467 @@ -###################################### -# R Source code file for plotting functions -# plotSailCoef is called by plot.sail and is not exported -# plotMain and plotInter are exported -# Author: Sahir Bhatnagar -# Created: 2016 -# Updated: April 9, 2018 -##################################### - -#' @importFrom grDevices hcl -plotSailCoef <- function(coefs, lambda, group, df, dev, vnames, environ, - alpha = 1, legend.loc, label = FALSE, log.l = TRUE, - norm = FALSE, ...) { - - # browser() - if (alpha < 0 | alpha > 1) { - warning("alpha must be in the range [0,1]. Setting alpha = 1") - alpha <- 1 - } - - if (norm) { # not implemented for now - # Y <- predict(x, type = "norm") - # index <- Y - # approx.f = 1 - # if (any(x$group == 0)) - # Y <- Y[-1, ] - # nonzero <- which(apply(abs(Y), 1, sum) != 0) - # Y <- Y[nonzero, ] - # g <- 1:nrow(Y) - } else { - if (length(dim(coefs)) == 3) { - beta <- matrix(coefs[, -1, , drop = FALSE], ncol = dim(coefs)[3]) - } else { - beta <- coefs - } - penalized <- which(group != 0) - nonzero <- which(apply(abs(beta), 1, sum) != 0) - ind <- intersect(penalized, nonzero) - Y <- as.matrix(beta[ind, , drop = FALSE]) - g <- as.numeric(as.factor(group[ind])) - } - p <- nrow(Y) - l <- lambda - n.g <- max(g) - if (log.l) { - l <- log(l) - index <- l - approx.f <- 0 - xlab <- expression(log(lambda)) - } else { - xlab <- expression(lambda) - index <- lambda - approx.f <- 0 - } - - ylims <- if (!missing(environ)) range(Y, environ) else range(Y) - plot.args <- list( - x = l, y = 1:length(l), ylim = ylims, - xlab = xlab, ylab = "", type = "n", - xlim = rev(range(l)), - # las = 1, - cex.lab = 1.5, - cex.axis = 1.5, - cex = 1.5, - # bty = "n", - # mai=c(1,1,0.1,0.2), - # tcl = -0.5, - # omi = c(0.2,1,0.2,0.2), - family = "serif" - ) - new.args <- list(...) - if (length(new.args)) { - new.plot.args <- new.args[names(new.args) %in% c( - names(par()), - names(formals(plot.default)) - )] - plot.args[names(new.plot.args)] <- new.plot.args - } - do.call("plot", plot.args) - if (plot.args$ylab == "") { - ylab <- if (norm) { - expression("||" * hat(theta) * "||") - } else { - expression(hat(theta)) - } - mtext(ylab, 2, 3.5, las = 1, adj = 0, cex = 2) - } - abline(h = 0, lwd = 0.8, col = "gray") - cols <- hcl( - h = seq(15, 375, len = max(4, n.g + 1)), l = 60, - c = 150, alpha = alpha - ) - cols <- if (n.g == 2) cols[c(1, 3)] else cols[1:n.g] - line.args <- list( - col = cols, lwd = 1 + 2 * exp(-p / 20), - lty = 1, pch = "" - ) - if (length(new.args)) { - line.args[names(new.args)] <- new.args - } - line.args$x <- l - line.args$y <- t(Y) - line.args$col <- line.args$col[g] - line.args$lty <- rep(line.args$lty, length.out = max(g)) - line.args$lty <- line.args$lty[g] - do.call("matlines", line.args) - if (!missing(environ)) lines(l, environ, lwd = line.args$lwd) - if (!missing(legend.loc)) { - legend.args <- list( - col = cols, lwd = line.args$lwd, - lty = line.args$lty, legend = vnames - ) - if (length(new.args)) { - new.legend.args <- new.args[names(new.args) %in% - names(formals(legend))] - legend.args[names(new.legend.args)] <- new.legend.args - } - legend.args$x <- legend.loc - do.call("legend", legend.args) - } - if (label) { - ypos <- Y[, ncol(Y)] - text(min(l), ypos, names(ypos), xpd = NA, adj = c( - 0, - NA - )) - } - - atdf <- pretty(index) - prettydf <- stats::approx( - x = index, y = df, xout = atdf, rule = 2, - method = "constant", f = approx.f - )$y - axis(3, - at = atdf, labels = prettydf, mgp = c(3, .3, 0), - tcl = NA, - cex.axis = 1.2 - ) -} - - - - - -#' @title Plot Estimated Component Smooth Functions for Main Effects -#' @description Takes a fitted sail object produced by \code{sail()} or -#' \code{cv.sail()$sail.fit} and plots the component smooth function for a -#' pre-specified variable at a given value of lambda and on the scale of the -#' linear predictor. Currently only implemented for \code{type="gaussian"} -#' @param object a fitted \code{sail} object as produced by \code{sail()} or -#' \code{cv.sail()$sail.fit} -#' @param x original data supplied to the original call to \code{\link{sail}} -#' @param xvar a character corresponding to the predictor to be plotted. Only -#' one variable name should be supplied, if more than one is supplied, only -#' the first element will be plotted. This variable name must be in -#' \code{colnames(x)}. -#' @param s a single value of the penalty parameter \code{lambda} at which -#' coefficients will be extracted via the \code{coef} method for objects of -#' class \code{"sail"}. If more than one is supplied, only the first one will -#' be used. -#' @param f.truth true function. Only used for simulation purposes when the -#' truth is known. The function takes as a input a numeric vector -#' corresponding the \code{xvar} column in \code{x} of length \code{nrow(x)}. -#' A second line will be plotted for the truth and a legend is added to the -#' plot. -#' @param col color of the line. The first element corresponds to the color used -#' for the estimated function and the second element is for the true function -#' (if \code{f.truth} is specified). Default: c("#D55E00", "#009E73") -#' @param legend.position position of the legend. Only used when \code{f.truth} -#' is specified. Default: 'bottomleft'. Can be a single keyword from the list -#' "bottomright", "bottom", "bottomleft", "left", "topleft", "top", -#' "topright", "right" and "center". This places the legend on the inside of -#' the plot frame at the given location. Partial argument matching is used. -#' @param rug adds a rug representation (1-d plot) of the data to the plot, logical. Default: TRUE. -#' @param ... other graphical paramters passed to \code{plot}. -#' @return A plot is produced and nothing is returned -#' @details The linear predictor \eqn{basis(xvar) * \beta_xvar} is -#' plotted against \code{xvar}, where \code{basis} is the expansion provided -#' in the original call to \code{sail}. -#' @examples -#' \dontrun{ -#' if(interactive()){ -#' # Parallel -#' library(doMC) -#' registerDoMC(cores = 4) -#' data("sailsim") -#' f.basis <- function(i) splines::bs(i, degree = 5) -#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nfolds = 10, parallel = TRUE) -#' # plot cv-error curve -#' plot(cvfit) -#' # non-zero estimated coefficients at lambda.min -#' predict(cvfit, type = "nonzero", s="lambda.min") -#' # plot main effect for X4 with a line for the truth also -#' plotMain(cvfit$sail.fit, x = sailsim$x, xvar = "X4", -#' s = cvfit$lambda.min, f.truth = sailsim$f4) -#' } -#' } -#' @seealso \code{\link{coef.sail}} \code{\link{predict.sail}}, \code{\link[graphics]{rug}} -#' @rdname plotMain -#' @importFrom graphics abline axis legend lines mtext par plot.default segments text -#' @importFrom stats coef -#' @export -plotMain <- function(object, x, xvar, s, f.truth, col = c("#D55E00", "#009E73"), - legend.position = "bottomleft", rug = TRUE, ...) { - - # browser() - if (length(xvar) > 1) { - xvar <- xvar[[1]] - warning("More than 1 xvar provided. Only first element will be plotted.") - } - - if (length(s) > 1) { - s <- s[[1]] - warning("More than 1 s value provided. Only first element will be used for the estimated coefficients.") - } - - ind <- object$group == which(object$vnames == xvar) - allCoefs <- coef(object, s = s) - a0 <- allCoefs[1, ] - betas <- as.matrix(allCoefs[object$main.effect.names[ind], , drop = FALSE]) - design.mat <- object$design[, object$main.effect.names[ind], drop = FALSE] - originalX <- x[, unique(object$group[ind])] - - # f.hat <- drop(a0 + design.mat %*% betas) - f.hat <- drop(design.mat %*% betas) - if (!missing(f.truth)) { - seqs <- seq(range(originalX)[1], range(originalX)[2], length.out = 100) - f.truth.eval <- f.truth(seqs) - ylims <- range(f.truth.eval, f.hat) - } else { - ylims <- range(f.hat) - } - - plot.args <- list( - x = originalX[order(originalX)], - y = f.hat[order(originalX)], - ylim = ylims, - xlab = xvar, - ylab = sprintf("f(%s)", xvar), - type = "n", - # xlim = rev(range(l)), - # las = 1, - cex.lab = 1.5, - cex.axis = 1.5, - cex = 1.5, - # bty = "n", - # mai=c(1,1,0.1,0.2), - # tcl = -0.5, - # omi = c(0.2,1,0.2,0.2), - family = "serif" - ) - new.args <- list(...) - if (length(new.args)) { - new.plot.args <- new.args[names(new.args) %in% c( - names(par()), - names(formals(plot.default)) - )] - plot.args[names(new.plot.args)] <- new.plot.args - } - do.call("plot", plot.args) - abline(h = 0, lwd = 1, col = "gray") - lines(originalX[order(originalX)], f.hat[order(originalX)], col = col[1], lwd = 3) - if (rug) graphics::rug(originalX, side = 1) - if (!missing(f.truth)) { - lines(seqs[order(seqs)], f.truth.eval[order(seqs)], col = col[2], lwd = 3) - } - if (!missing(f.truth)) { - legend(legend.position, - c("Estimated", "Truth"), - col = col, cex = 1, bty = "n", lwd = 3 - ) - } -} - - - -#' @title Plot Interaction Effects from sail object -#' @description Takes a fitted sail object produced by \code{sail()} or -#' \code{cv.sail()$sail.fit} and plots a \code{\link[graphics]{persp}} for a -#' pre-specified variable at a given value of lambda and on the scale of the -#' linear predictor. Currently only implemented for \code{type="gaussian"} -#' @inheritParams plotMain -#' @param f.truth true function. Only used for simulation purposes when the -#' truth is known. The function takes as a input two numeric vectors e.g. -#' \code{f(x,e)} corresponding the \code{xvar} column in \code{x} of length -#' \code{nrow(x)} and the exposure variable contained in the \code{sail -#' object}. A second \code{persp} will be plotted for the truth -#' @param interation.only if \code{TRUE} only the interaction part is used to -#' calculate the linear predictor, i.e., \eqn{linear predictor = E * f(X) * -#' interaction_effects}. If \code{FALSE}, then \eqn{linear predictor = E * -#' \beta_E + f(X) * interaction_effects + E * f(X) * interaction_effects}. -#' Default: TRUE -#' @param truthonly only plot the truth. \code{f.truth} must be specified if -#' this argument is set to \code{TRUE}. Default: FALSE -#' @param npoints number of points in the grid to calculate the perspective -#' plot. Default: 30 -#' @param title_z title for the plot, Default: '' -#' @param xlab chracter for xlabel. if missing, variable name is used -#' @param ylab chracter for ylabel. if missing, variable name is used -#' @param zlab chracter for zlabel. if missing, variable name is used -#' @param ... currently ignored -#' @return A plot is produced and nothing is returned -#' @examples -#' \dontrun{ -#' if(interactive()){ -#' # Parallel -#' library(doMC) -#' registerDoMC(cores = 4) -#' data("sailsim") -#' f.basis <- function(i) splines::bs(i, degree = 5) -#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nfolds = 10, parallel = TRUE) -#' # plot cv-error curve -#' plot(cvfit) -#' # non-zero estimated coefficients at lambda.min -#' predict(cvfit, type = "nonzero", s="lambda.min") -#' # plot interaction effect for X4 and the true interaction effect also -#' plotInter(cvfit$sail.fit, x = sailsim$x, xvar = "X3", -#' f.truth = sailsim$f4.inter, -#' s = cvfit$lambda.min, -#' title_z = "Estimated") -#' } -#' } -#' @seealso \code{\link[graphics]{persp}} \code{\link{coef.sail}} -#' \code{\link{predict.sail}}, \code{\link[graphics]{rug}} -#' @rdname plotInter -#' @importFrom graphics abline axis legend lines mtext par plot.default segments text -#' @importFrom stats coef -#' @export -plotInter <- function(object, x, xvar, s, f.truth, interation.only = TRUE, truthonly = FALSE, - npoints = 30, col = c("#56B4E9", "#D55E00"), title_z = "", xlab, ylab, zlab, - ...) { - - # browser() - if (length(xvar) > 1) { - xvar <- xvar[[1]] - warning("More than 1 xvar provided. Only first element will be plotted.") - } - - if (length(s) > 1) { - s <- s[[1]] - warning("More than 1 s value provided. Only first element will be used for the estimated coefficients.") - } - - ind <- object$group == which(object$vnames == xvar) - allCoefs <- coef(object, s = s) - a0 <- allCoefs[1, ] - - betas <- as.matrix(allCoefs[object$main.effect.names[ind], , drop = FALSE]) - alphas <- as.matrix(allCoefs[object$interaction.names[ind], , drop = FALSE]) - betaE <- as.matrix(allCoefs["E", , drop = FALSE]) - - design.mat.main <- object$design[, object$main.effect.names[ind], drop = FALSE] - design.mat.int <- object$design[, object$interaction.names[ind], drop = FALSE] - originalE <- object$design[, "E", drop = FALSE] # this is the centered E - originalX <- x[, unique(object$group[ind])] - - # f.hat <- drop(a0 + design.mat %*% betas) - # f.hat <- drop(originalE %*% betaE + design.mat.main %*% betas + design.mat.int %*% alphas) - - # all.equal((e * standardize(splines::bs(x, df = object$df, degree = object$degree))$x), - # sweep(standardize(splines::bs(x, df = object$df, degree = object$degree))$x, 1, e, FUN = "*")) - - x <- seq(range(originalX)[1], range(originalX)[2], length.out = npoints) - e <- seq(range(originalE)[1], range(originalE)[2], length.out = npoints) - - # show interaction effect only for simulation - if (interation.only) { - f.est <- function(X, E) { - # E * as.vector(betaE) + standardize(splines::bs(X, df = object$df, degree = object$degree))$x %*% betas + - (drop(standardize(E, center = object$center.e)$x) * standardize(object$basis(X), center = object$center.e)$x) %*% alphas - # (E * standardize(object$basis(X), center = FALSE)$x) %*% alphas - } - } else { - f.est <- function(X, E) { - standardize(E, center = object$center.e)$x * as.vector(betaE) + - standardize(object$basis(X), center = object$center.e)$x %*% betas + - (drop(standardize(E, center = object$center.e)$x) * standardize(object$basis(X), center = object$center.e)$x) %*% alphas - } - } - - # f.truth <- function(x, e) { e * DT$f4(x) } - z.est <- outer(x, e, f.est) - - if (!missing(f.truth)) { - z.truth <- outer(x, e, f.truth) - z_range <- c(min(z.est, z.truth), max(z.est, z.truth)) - } else { - z_range <- c(min(z.est), max(z.est)) - } - - op <- par(bg = "white") - - # c(bottom, left, top, right) - if (truthonly) { - par(mfrow = c(1, 1), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0)) - par(mai = c(0., 0.2, 0.4, 0.)) - graphics::persp(x, e, z.truth, - zlim = z_range, - theta = 30, phi = 30, - ltheta = 120, expand = 0.5, - r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, - nticks = 5, - # ticktype="detailed", - col = col[2], - cex.lab = 3, - cex.main = 3, - xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, - ylab = if(missing(ylab)) "X_E" else ylab, - zlab = if(missing(zlab)) "Y" else zlab, - main = "Truth" - ) - } else if (!missing(f.truth)) { - par(mfrow = c(1, 2), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0)) - par(mai = c(0., 0.8, 0.6, 0.)) - graphics::persp(x, e, z.truth, - zlim = z_range, - theta = 30, phi = 30, - ltheta = 120, expand = 0.5, - r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, - nticks = 5, - # ticktype="detailed", - col = col[2], - cex.lab = 3, - cex.main = 3, - xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, - ylab = if(missing(ylab)) "X_E" else ylab, - zlab = if(missing(zlab)) "Y" else zlab, main = "Truth" - ) - graphics::persp(x, e, z.est, - theta = 30, phi = 30, - ltheta = 120, expand = 0.5, - r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, - nticks = 5, - # zlim = z_range, - cex.lab = 3, - cex.main = 3, - # ticktype="detailed", - col = col[1], - xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, - ylab = if(missing(ylab)) "X_E" else ylab, - zlab = if(missing(zlab)) "Y" else zlab, - main = title_z - ) - } else { - par(mfrow = c(1, 1), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0)) - par(mai = c(0., 0.2, 0.4, 0.)) - graphics::persp(x, e, z.est, - cex.lab = 3, - cex.main = 3, - theta = 30, phi = 30, - ltheta = 120, expand = 0.5, - r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, - nticks = 5, - zlim = z_range, - col = col[1], - # xlab=sprintf("f(x_%s)",as.numeric(gsub("X","",4))), - xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, - ylab = if(missing(ylab)) "X_E" else ylab, - zlab = if(missing(zlab)) "Y" else zlab, - # main=sprintf("Estimated Interaction Effect for %s",xvar) - main = title_z - ) - } -} +###################################### +# R Source code file for plotting functions +# plotSailCoef is called by plot.sail and is not exported +# plotMain and plotInter are exported +# Author: Sahir Bhatnagar +# Created: 2016 +# Updated: April 9, 2018 +##################################### + +#' @importFrom grDevices hcl +plotSailCoef <- function(coefs, lambda, group, df, dev, vnames, environ, + alpha = 1, legend.loc, label = FALSE, log.l = TRUE, + norm = FALSE, ...) { + + # browser() + if (alpha < 0 | alpha > 1) { + warning("alpha must be in the range [0,1]. Setting alpha = 1") + alpha <- 1 + } + + if (norm) { # not implemented for now + # Y <- predict(x, type = "norm") + # index <- Y + # approx.f = 1 + # if (any(x$group == 0)) + # Y <- Y[-1, ] + # nonzero <- which(apply(abs(Y), 1, sum) != 0) + # Y <- Y[nonzero, ] + # g <- 1:nrow(Y) + } else { + if (length(dim(coefs)) == 3) { + beta <- matrix(coefs[, -1, , drop = FALSE], ncol = dim(coefs)[3]) + } else { + beta <- coefs + } + penalized <- which(group != 0) + nonzero <- which(apply(abs(beta), 1, sum) != 0) + ind <- intersect(penalized, nonzero) + Y <- as.matrix(beta[ind, , drop = FALSE]) + g <- as.numeric(as.factor(group[ind])) + } + p <- nrow(Y) + l <- lambda + n.g <- max(g) + if (log.l) { + l <- log(l) + index <- l + approx.f <- 0 + xlab <- expression(log(lambda)) + } else { + xlab <- expression(lambda) + index <- lambda + approx.f <- 0 + } + + ylims <- if (!missing(environ)) range(Y, environ) else range(Y) + plot.args <- list( + x = l, y = 1:length(l), ylim = ylims, + xlab = xlab, ylab = "", type = "n", + xlim = rev(range(l)), + # las = 1, + cex.lab = 1.5, + cex.axis = 1.5, + cex = 1.5, + # bty = "n", + # mai=c(1,1,0.1,0.2), + # tcl = -0.5, + # omi = c(0.2,1,0.2,0.2), + family = "serif" + ) + new.args <- list(...) + if (length(new.args)) { + new.plot.args <- new.args[names(new.args) %in% c( + names(par()), + names(formals(plot.default)) + )] + plot.args[names(new.plot.args)] <- new.plot.args + } + do.call("plot", plot.args) + if (plot.args$ylab == "") { + ylab <- if (norm) { + expression("||" * hat(theta) * "||") + } else { + expression(hat(theta)) + } + mtext(ylab, 2, 3.5, las = 1, adj = 0, cex = 2) + } + abline(h = 0, lwd = 0.8, col = "gray") + cols <- hcl( + h = seq(15, 375, len = max(4, n.g + 1)), l = 60, + c = 150, alpha = alpha + ) + cols <- if (n.g == 2) cols[c(1, 3)] else cols[1:n.g] + line.args <- list( + col = cols, lwd = 1 + 2 * exp(-p / 20), + lty = 1, pch = "" + ) + if (length(new.args)) { + line.args[names(new.args)] <- new.args + } + line.args$x <- l + line.args$y <- t(Y) + line.args$col <- line.args$col[g] + line.args$lty <- rep(line.args$lty, length.out = max(g)) + line.args$lty <- line.args$lty[g] + do.call("matlines", line.args) + if (!missing(environ)) lines(l, environ, lwd = line.args$lwd) + if (!missing(legend.loc)) { + legend.args <- list( + col = cols, lwd = line.args$lwd, + lty = line.args$lty, legend = vnames + ) + if (length(new.args)) { + new.legend.args <- new.args[names(new.args) %in% + names(formals(legend))] + legend.args[names(new.legend.args)] <- new.legend.args + } + legend.args$x <- legend.loc + do.call("legend", legend.args) + } + if (label) { + ypos <- Y[, ncol(Y)] + text(min(l), ypos, names(ypos), xpd = NA, adj = c( + 0, + NA + )) + } + + atdf <- pretty(index) + prettydf <- stats::approx( + x = index, y = df, xout = atdf, rule = 2, + method = "constant", f = approx.f + )$y + axis(3, + at = atdf, labels = prettydf, mgp = c(3, .3, 0), + tcl = NA, + cex.axis = 1.2 + ) +} + + + + + +#' @title Plot Estimated Component Smooth Functions for Main Effects +#' @description Takes a fitted sail object produced by \code{sail()} or +#' \code{cv.sail()$sail.fit} and plots the component smooth function for a +#' pre-specified variable at a given value of lambda and on the scale of the +#' linear predictor. Currently only implemented for \code{type="gaussian"} +#' @param object a fitted \code{sail} object as produced by \code{sail()} or +#' \code{cv.sail()$sail.fit} +#' @param x original data supplied to the original call to \code{\link{sail}} +#' @param xvar a character corresponding to the predictor to be plotted. Only +#' one variable name should be supplied, if more than one is supplied, only +#' the first element will be plotted. This variable name must be in +#' \code{colnames(x)}. +#' @param s a single value of the penalty parameter \code{lambda} at which +#' coefficients will be extracted via the \code{coef} method for objects of +#' class \code{"sail"}. If more than one is supplied, only the first one will +#' be used. +#' @param f.truth true function. Only used for simulation purposes when the +#' truth is known. The function takes as a input a numeric vector +#' corresponding the \code{xvar} column in \code{x} of length \code{nrow(x)}. +#' A second line will be plotted for the truth and a legend is added to the +#' plot. +#' @param col color of the line. The first element corresponds to the color used +#' for the estimated function and the second element is for the true function +#' (if \code{f.truth} is specified). Default: c("#D55E00", "#009E73") +#' @param legend.position position of the legend. Only used when \code{f.truth} +#' is specified. Default: 'bottomleft'. Can be a single keyword from the list +#' "bottomright", "bottom", "bottomleft", "left", "topleft", "top", +#' "topright", "right" and "center". This places the legend on the inside of +#' the plot frame at the given location. Partial argument matching is used. +#' @param rug adds a rug representation (1-d plot) of the data to the plot, logical. Default: TRUE. +#' @param ... other graphical paramters passed to \code{plot}. +#' @return A plot is produced and nothing is returned +#' @details The linear predictor \eqn{basis(xvar) * \beta_xvar} is +#' plotted against \code{xvar}, where \code{basis} is the expansion provided +#' in the original call to \code{sail}. +#' @examples +#' f.basis <- function(i) splines::bs(i, degree = 3) +#' # Parallel +#' library(doParallel) +#' cl <- makeCluster(2) +#' registerDoParallel(cl) +#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, +#' parallel = TRUE, nlambda = 10, +#' maxit = 100, basis = f.basis, +#' nfolds = 3, dfmax = 10) +#' stopCluster(cl) +#' # plot cv-error curve +#' plot(cvfit) +#' # non-zero estimated coefficients at lambda.min +#' predict(cvfit, type = "nonzero", s="lambda.min") +#' # plot main effect for X4 with a line for the truth also +#' plotMain(cvfit$sail.fit, x = sailsim$x, xvar = "X4", +#' s = cvfit$lambda.min, f.truth = sailsim$f4) +#' @seealso \code{\link{coef.sail}} \code{\link{predict.sail}}, \code{\link[graphics]{rug}} +#' @rdname plotMain +#' @importFrom graphics abline axis legend lines mtext par plot.default segments text +#' @importFrom stats coef +#' @export +plotMain <- function(object, x, xvar, s, f.truth, col = c("#D55E00", "#009E73"), + legend.position = "bottomleft", rug = TRUE, ...) { + + # browser() + if (length(xvar) > 1) { + xvar <- xvar[[1]] + warning("More than 1 xvar provided. Only first element will be plotted.") + } + + if (length(s) > 1) { + s <- s[[1]] + warning("More than 1 s value provided. Only first element will be used for the estimated coefficients.") + } + + ind <- object$group == which(object$vnames == xvar) + allCoefs <- coef(object, s = s) + a0 <- allCoefs[1, ] + betas <- as.matrix(allCoefs[object$main.effect.names[ind], , drop = FALSE]) + design.mat <- object$design[, object$main.effect.names[ind], drop = FALSE] + originalX <- x[, unique(object$group[ind])] + + # f.hat <- drop(a0 + design.mat %*% betas) + f.hat <- drop(design.mat %*% betas) + if (!missing(f.truth)) { + seqs <- seq(range(originalX)[1], range(originalX)[2], length.out = 100) + f.truth.eval <- f.truth(seqs) + ylims <- range(f.truth.eval, f.hat) + } else { + ylims <- range(f.hat) + } + + plot.args <- list( + x = originalX[order(originalX)], + y = f.hat[order(originalX)], + ylim = ylims, + xlab = xvar, + ylab = sprintf("f(%s)", xvar), + type = "n", + # xlim = rev(range(l)), + # las = 1, + cex.lab = 1.5, + cex.axis = 1.5, + cex = 1.5, + # bty = "n", + # mai=c(1,1,0.1,0.2), + # tcl = -0.5, + # omi = c(0.2,1,0.2,0.2), + family = "serif" + ) + new.args <- list(...) + if (length(new.args)) { + new.plot.args <- new.args[names(new.args) %in% c( + names(par()), + names(formals(plot.default)) + )] + plot.args[names(new.plot.args)] <- new.plot.args + } + do.call("plot", plot.args) + abline(h = 0, lwd = 1, col = "gray") + lines(originalX[order(originalX)], f.hat[order(originalX)], col = col[1], lwd = 3) + if (rug) graphics::rug(originalX, side = 1) + if (!missing(f.truth)) { + lines(seqs[order(seqs)], f.truth.eval[order(seqs)], col = col[2], lwd = 3) + } + if (!missing(f.truth)) { + legend(legend.position, + c("Estimated", "Truth"), + col = col, cex = 1, bty = "n", lwd = 3 + ) + } +} + + + +#' @title Plot Interaction Effects from sail object +#' @description Takes a fitted sail object produced by \code{sail()} or +#' \code{cv.sail()$sail.fit} and plots a \code{\link[graphics]{persp}} for a +#' pre-specified variable at a given value of lambda and on the scale of the +#' linear predictor. Currently only implemented for \code{type="gaussian"} +#' @inheritParams plotMain +#' @param f.truth true function. Only used for simulation purposes when the +#' truth is known. The function takes as a input two numeric vectors e.g. +#' \code{f(x,e)} corresponding the \code{xvar} column in \code{x} of length +#' \code{nrow(x)} and the exposure variable contained in the \code{sail +#' object}. A second \code{persp} will be plotted for the truth +#' @param interation.only if \code{TRUE} only the interaction part is used to +#' calculate the linear predictor, i.e., \eqn{linear predictor = E * f(X) * +#' interaction_effects}. If \code{FALSE}, then \eqn{linear predictor = E * +#' \beta_E + f(X) * interaction_effects + E * f(X) * interaction_effects}. +#' Default: TRUE +#' @param truthonly only plot the truth. \code{f.truth} must be specified if +#' this argument is set to \code{TRUE}. Default: FALSE +#' @param npoints number of points in the grid to calculate the perspective +#' plot. Default: 30 +#' @param title_z title for the plot, Default: '' +#' @param xlab character for xlabel. if missing, variable name is used +#' @param ylab character for ylabel. if missing, variable name is used +#' @param zlab character for zlabel. if missing, variable name is used +#' @param ... currently ignored +#' @return A plot is produced and nothing is returned +#' @examples +#' f.basis <- function(i) splines::bs(i, degree = 3) +#' # Parallel +#' library(doParallel) +#' cl <- makeCluster(2) +#' registerDoParallel(cl) +#' cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, +#' parallel = TRUE, nlambda = 10, +#' maxit = 100, basis = f.basis, +#' nfolds = 3, dfmax = 10) +#' stopCluster(cl) +#' # plot cv-error curve +#' plot(cvfit) +#' # non-zero estimated coefficients at lambda.min +#' predict(cvfit, type = "nonzero", s="lambda.min") +#' # plot interaction effect for X4 and the true interaction effect also +#' plotInter(cvfit$sail.fit, x = sailsim$x, xvar = "X3", +#' f.truth = sailsim$f4.inter, +#' s = cvfit$lambda.min, +#' title_z = "Estimated") +#' @seealso \code{\link[graphics]{persp}} \code{\link{coef.sail}} +#' \code{\link{predict.sail}}, \code{\link[graphics]{rug}} +#' @rdname plotInter +#' @importFrom graphics abline axis legend lines mtext par plot.default segments text +#' @importFrom stats coef +#' @export +plotInter <- function(object, x, xvar, s, f.truth, interation.only = TRUE, truthonly = FALSE, + npoints = 30, col = c("#56B4E9", "#D55E00"), title_z = "", xlab, ylab, zlab, + ...) { + + # browser() + if (length(xvar) > 1) { + xvar <- xvar[[1]] + warning("More than 1 xvar provided. Only first element will be plotted.") + } + + if (length(s) > 1) { + s <- s[[1]] + warning("More than 1 s value provided. Only first element will be used for the estimated coefficients.") + } + + ind <- object$group == which(object$vnames == xvar) + allCoefs <- coef(object, s = s) + a0 <- allCoefs[1, ] + + betas <- as.matrix(allCoefs[object$main.effect.names[ind], , drop = FALSE]) + alphas <- as.matrix(allCoefs[object$interaction.names[ind], , drop = FALSE]) + betaE <- as.matrix(allCoefs["E", , drop = FALSE]) + + design.mat.main <- object$design[, object$main.effect.names[ind], drop = FALSE] + design.mat.int <- object$design[, object$interaction.names[ind], drop = FALSE] + originalE <- object$design[, "E", drop = FALSE] # this is the centered E + originalX <- x[, unique(object$group[ind])] + + # f.hat <- drop(a0 + design.mat %*% betas) + # f.hat <- drop(originalE %*% betaE + design.mat.main %*% betas + design.mat.int %*% alphas) + + # all.equal((e * standardize(splines::bs(x, df = object$df, degree = object$degree))$x), + # sweep(standardize(splines::bs(x, df = object$df, degree = object$degree))$x, 1, e, FUN = "*")) + + x <- seq(range(originalX)[1], range(originalX)[2], length.out = npoints) + e <- seq(range(originalE)[1], range(originalE)[2], length.out = npoints) + + # show interaction effect only for simulation + if (interation.only) { + f.est <- function(X, E) { + # E * as.vector(betaE) + standardize(splines::bs(X, df = object$df, degree = object$degree))$x %*% betas + + (drop(standardize(E, center = object$center.e)$x) * standardize(object$basis(X), center = object$center.e)$x) %*% alphas + # (E * standardize(object$basis(X), center = FALSE)$x) %*% alphas + } + } else { + f.est <- function(X, E) { + standardize(E, center = object$center.e)$x * as.vector(betaE) + + standardize(object$basis(X), center = object$center.e)$x %*% betas + + (drop(standardize(E, center = object$center.e)$x) * standardize(object$basis(X), center = object$center.e)$x) %*% alphas + } + } + + # f.truth <- function(x, e) { e * DT$f4(x) } + z.est <- outer(x, e, f.est) + + if (!missing(f.truth)) { + z.truth <- outer(x, e, f.truth) + z_range <- c(min(z.est, z.truth), max(z.est, z.truth)) + } else { + z_range <- c(min(z.est), max(z.est)) + } + + + + # c(bottom, left, top, right) + if (truthonly) { + oldpar <- par(mfrow = c(1, 1), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0), + mai = c(0., 0.2, 0.4, 0.), bg = "white") + on.exit(par(oldpar)) + graphics::persp(x, e, z.truth, + zlim = z_range, + theta = 30, phi = 30, + ltheta = 120, expand = 0.5, + r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, + nticks = 5, + # ticktype="detailed", + col = col[2], + cex.lab = 3, + cex.main = 3, + xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, + ylab = if(missing(ylab)) "X_E" else ylab, + zlab = if(missing(zlab)) "Y" else zlab, + main = "Truth" + ) + } else if (!missing(f.truth)) { + oldpar <- par(mfrow = c(1, 2), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0), + mai = c(0., 0.8, 0.6, 0.), bg = "white") + on.exit(par(oldpar)) + graphics::persp(x, e, z.truth, + zlim = z_range, + theta = 30, phi = 30, + ltheta = 120, expand = 0.5, + r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, + nticks = 5, + # ticktype="detailed", + col = col[2], + cex.lab = 3, + cex.main = 3, + xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, + ylab = if(missing(ylab)) "X_E" else ylab, + zlab = if(missing(zlab)) "Y" else zlab, main = "Truth" + ) + graphics::persp(x, e, z.est, + theta = 30, phi = 30, + ltheta = 120, expand = 0.5, + r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, + nticks = 5, + # zlim = z_range, + cex.lab = 3, + cex.main = 3, + # ticktype="detailed", + col = col[1], + xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, + ylab = if(missing(ylab)) "X_E" else ylab, + zlab = if(missing(zlab)) "Y" else zlab, + main = title_z + ) + } else { + oldpar <- par(mfrow = c(1, 1), tcl = -0.5, family = "serif", omi = c(0.2, 0.2, 0, 0), + mai = c(0., 0.2, 0.4, 0.), bg = "white") + on.exit(par(oldpar)) + graphics::persp(x, e, z.est, + cex.lab = 3, + cex.main = 3, + theta = 30, phi = 30, + ltheta = 120, expand = 0.5, + r = 2, shade = 0.3, axes = TRUE, scale = TRUE, box = T, + nticks = 5, + zlim = z_range, + col = col[1], + # xlab=sprintf("f(x_%s)",as.numeric(gsub("X","",4))), + xlab = if(missing(xlab)) sprintf("f(%s)", xvar) else xlab, + ylab = if(missing(ylab)) "X_E" else ylab, + zlab = if(missing(zlab)) "Y" else zlab, + # main=sprintf("Estimated Interaction Effect for %s",xvar) + main = title_z + ) + } +} diff --git a/R/sail.R b/R/sail.R index 23a2fe3..0483aee 100644 --- a/R/sail.R +++ b/R/sail.R @@ -5,7 +5,7 @@ #' regression method that ensures the interaction term is non-zero only if its #' corresponding main-effects are non-zero. This model only considers the #' interactions between a single exposure (E) variable and a high-dimensional -#' matrix (X). Additve (non-linear) main effects and interactions can be +#' matrix (X). Additive (non-linear) main effects and interactions can be #' specified by the user. This can also be seen as a varying-coefficient #' model. #' @param x input matrix of dimension \code{n x p}, where \code{n} is the number @@ -152,7 +152,8 @@ #' # we specify dfmax to early stop the solution path to #' # limit the execution time of the example #' fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, -#' basis = f.basis, nlambda = 100, dfmax = 10) +#' basis = f.basis, nlambda = 10, dfmax = 10, +#' maxit = 100) #' #' # estimated coefficients at each value of lambda #' coef(fit) @@ -162,16 +163,12 @@ #' #' #predicted response at a specific value of lambda #' predict(fit, s = 0.5) -#' \dontrun{ -#' if(interactive()){ #' # plot solution path for main effects and interactions #' plot(fit) #' # plot solution path only for main effects #' plot(fit, type = "main") #' # plot solution path only for interactions #' plot(fit, type = "interaction") -#' } -#' } #' #' @references Jerome Friedman, Trevor Hastie, Robert Tibshirani (2010). #' Regularization Paths for Generalized Linear Models via Coordinate Descent. diff --git a/R/simulations.R b/R/simulations.R index 91f5a6a..ae65622 100644 --- a/R/simulations.R +++ b/R/simulations.R @@ -1,4 +1,4 @@ -#' @title Simulation Scenarion from Bhatnagar et al. (2018+) sail paper +#' @title Simulation Scenario from Bhatnagar et al. (2018+) sail paper #' @description generates the different simulation scenarios. This function is #' not intended to be called directly by users. See \code{\link{gendata}} #' @inheritParams gendata diff --git a/README.md b/README.md index b3e3ae2..163c17d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # sail: Sparse Additive Interaction Learning + [![Travis build status](https://travis-ci.org/sahirbhatnagar/sail.svg?branch=master)](https://travis-ci.org/sahirbhatnagar/sail) [![Coverage status](https://codecov.io/gh/sahirbhatnagar/sail/branch/master/graph/badge.svg)](https://codecov.io/github/sahirbhatnagar/sail?branch=master) [![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/sail)](https://cran.r-project.org/package=sail) +[![AppVeyor build status](https://ci.appveyor.com/api/projects/status/github/sahirbhatnagar/sail?branch=master&svg=true)](https://ci.appveyor.com/project/sahirbhatnagar/sail) + `R` software package to fit sparse additive interaction models with the strong heredity property. Interactions are limited to a single exposure or environment variable. The following figure (based on simulated data) gives an idea of the situation our method is trying to capture: @@ -28,7 +31,7 @@ See the [online vignette](http://sahirbhatnagar.com/sail/) for details about the This method requires four inputs (let _n_ be the number of observations and _p_ the number of **X** variables): 1. **X**: _n_ x _p_ matrix of covariates. Can be high-dimensional, i.e., p >> n. Can also be continuous, categorical or a combination of both. 2. **Y**: a continuous response of length _n_ -3. **E**: an exposure variable of length _n_. Can be continous or categorical. +3. **E**: an exposure variable of length _n_. Can be continuous or categorical. 4. A basis expansion function **f(X_j)** to be applied to each column of **X**, for example ```R @@ -72,5 +75,5 @@ You can see the most recent changes to the package in the [NEWS.md file](https:/ ## Code of Conduct -Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). +Please note that this project is released with a [Contributor Code of Conduct](https://sahirbhatnagar.com/sail/CODE_OF_CONDUCT.html). By participating in this project you agree to abide by its terms. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..3a75e16 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,52 @@ +# DO NOT CHANGE the "init" and "install" sections below + +# Download script file from GitHub +init: + ps: | + $ErrorActionPreference = "Stop" + Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" + Import-Module '..\appveyor-tool.ps1' + +install: + ps: Bootstrap + +cache: + - C:\RLibrary + +environment: + NOT_CRAN: true + # env vars that may need to be set, at least temporarily, from time to time + # see https://github.com/krlmlr/r-appveyor#readme for details + # USE_RTOOLS: true + # R_REMOTES_STANDALONE: true + +# Adapt as necessary starting from here + +build_script: + - travis-tool.sh install_deps + +test_script: + - travis-tool.sh run_tests + +on_failure: + - 7z a failure.zip *.Rcheck\* + - appveyor PushArtifact failure.zip + +artifacts: + - path: '*.Rcheck\**\*.log' + name: Logs + + - path: '*.Rcheck\**\*.out' + name: Logs + + - path: '*.Rcheck\**\*.fail' + name: Logs + + - path: '*.Rcheck\**\*.Rout' + name: Logs + + - path: '\*_*.tar.gz' + name: Bits + + - path: '\*_*.zip' + name: Bits diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..0cff18c --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,49 @@ +## Test environments +* local R installation, R 3.6.1 +* ubuntu 16.04 (on travis-ci), R 3.6.1 +* win-builder (devel) + +## R CMD check results + +0 errors | 0 warnings | 1 note + +* This is a new release. + + + + +## Additional CRAN comments (Dec 1, 2019) + +### Please make sure that you do not change the user's options, par or working directory. If you really have to do so, please ensure with an *immediate* call of on.exit() that the settings are reset when the function is exited. + +I have used the `on.exit()` function in the `plotInter()`, `plot.sail()` function to fix this issue + +#### Do really all of your examples need to be wrapped in if(interactive()) ? + +I have removed the `interactive()` wrapper around most of the examples. + + +## Additional CRAN comments (Nov 25, 2019) + +### Please only capitalize names and sentence beginnings in the description. + +Fixed + +### Please ensure that you do not use more than 2 cores in your examples. + +Fixed + +### \dontrun{} should be only used if the example really cannot be executed (e.g. because of missing additional software, missing API keys, ...) by the user. That's why wrapping examples in \dontrun{} adds the comment ("# Not run:") as a warning for the user. Does not seem necessary, as you wrapped it in if(interactive()) + +I have removed \dontrun{} from all of the examples. + + +### You write information messages to the console that cannot be easily suppressed. It is more R like to generate objects that can be used to extract the information a user is interested in, and then print() that object. Instead of print()/cat() rather use message()/warning() or if(verbose)cat(..) if you really have to write text to the console. (except for print() and summary() functions) + +I have replaced `cat()` in the `kkt()` function with `warning()` + + +#### Please halve these tests runtimes: The overall threshold for the whole package check on CRAN is roughly 10 min. This had 15 min. + +Fixed. I have significantly reduced the tests times. + diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..076bdf3 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,174 @@ + + + + + + + + +Page not found (404) • sail + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+
+ + +Content not found. Please use links in the navbar. + +
+ +
+ + + + +
+ + + + + + + + + + + diff --git a/docs/CODE_OF_CONDUCT.html b/docs/CODE_OF_CONDUCT.html index 85d5d38..303d80b 100644 --- a/docs/CODE_OF_CONDUCT.html +++ b/docs/CODE_OF_CONDUCT.html @@ -1,6 +1,6 @@ - + @@ -8,28 +8,47 @@ Contributor Code of Conduct • sail + - + - + + - + - + + - + + + + + - + + + + + + + + + + + + - + + - - @@ -50,14 +65,15 @@ @@ -132,31 +143,40 @@

Contributor Code of Conduct

+ - + + + diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index e5443ee..176c87e 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -1,6 +1,6 @@ - + @@ -8,28 +8,47 @@ License • sail + - + - + + - + - + + - + + + + + - + + + + + + + + + + + + - + + - - @@ -50,14 +65,15 @@ - + + + diff --git a/docs/articles/index.html b/docs/articles/index.html index 3155d55..a4968e9 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -1,6 +1,6 @@ - + @@ -8,28 +8,47 @@ Articles • sail + - + - + + - + - + + - + + + + + - + + + + + + + + + + + + - + + - - @@ -50,14 +65,15 @@ + - + + + diff --git a/docs/articles/introduction-to-sail.html b/docs/articles/introduction-to-sail.html index b870a27..094010a 100644 --- a/docs/articles/introduction-to-sail.html +++ b/docs/articles/introduction-to-sail.html @@ -1,35 +1,39 @@ - + Introduction to the sail package • sail - - - - + + + + + + + - +
-

sail is a package that fits a linear model with non-linear interactions via penalized maximum likelihood. The regularization path is computed at a grid of values for the regularization parameter \(\lambda\) and a fixed value of the second regularization parameter \(\alpha\). The method enforces the strong heredity property, i.e., an interaction is selected only if its corresponding main effects are also included. The interactions are limited to a single exposure variable, i.e., \(y \sim e + x_1 + x_2 + e*x_1 + e*x_2 + \epsilon\). Furthermore, this package allows a user-defined basis expansion on the \(x\) variables to allow for non-linear effects. The default is bsplines (e.g. splines::bs(x, 5)). It currently only fits linear models (binomial models are due in the next release).

+

sail is a package that fits a linear model with non-linear interactions via penalized maximum likelihood. The regularization path is computed at a grid of values for the regularization parameter \(\lambda\) and a fixed value of the second regularization parameter \(\alpha\). The method enforces the strong heredity property, i.e., an interaction is selected only if its corresponding main effects are also included. The interactions are limited to a single exposure variable, i.e., \(y \sim e + x_1 + x_2 + e*x_1 + e*x_2 + \epsilon\). Furthermore, this package allows a user-defined basis expansion on the \(x\) variables to allow for non-linear effects. The default is bsplines (e.g. splines::bs(x, 5)). It currently only fits linear models (binomial models are due in the next release).

Model

-Let \(Y=(Y_1, \ldots, Y_n) \in \mathbb{R}^n\) be a continuous outcome variable, a binary or continuous environment vector, a matrix of predictors, and \(\varepsilon = (\varepsilon_1, \ldots, \varepsilon_n) \in \mathbb{R}^n\) a vector of i.i.d random variables with mean 0. Furthermore let \(f_j: \mathbb{R} \rightarrow \mathbb{R}\) be a smoothing method for variable \(X_j\) by a projection on to a set of basis functions: -\[\begin{equation} +

Let \(Y=(Y_1, \ldots, Y_n) \in \mathbb{R}^n\) be a continuous outcome variable, a binary or continuous environment vector, a matrix of predictors, and \(\varepsilon = (\varepsilon_1, \ldots, \varepsilon_n) \in \mathbb{R}^n\) a vector of i.i.d random variables with mean 0. Furthermore let \(f_j: \mathbb{R} \rightarrow \mathbb{R}\) be a smoothing method for variable \(X_j\) by a projection on to a set of basis functions: \[\begin{equation} f_j(X_j) = \sum_{\ell = 1}^{m_j} \psi_{j\ell}(X_j) \beta_{j\ell} \label{eq:smooth} -\end{equation}\] -Here, the \(\left\lbrace \psi_{j\ell} \right\rbrace_1^{m_j}\) are a family of basis functions in \(X_j\)~. Let \(\boldsymbol{\Psi}_j\) be the \(n \times m_j\) matrix of evaluations of the \(\psi_{j\ell}\) and for \(j = 1, \ldots, p\), i.e., \(\boldsymbol{\theta}_j\) is a \(m_j\)-dimensional column vector of basis coefficients for the \(j\)th main effect. In this article we consider an additive interaction regression model of the form -\[\begin{align} +\end{equation}\] Here, the \(\left\lbrace \psi_{j\ell} \right\rbrace_1^{m_j}\) are a family of basis functions in \(X_j\)~. Let \(\boldsymbol{\Psi}_j\) be the \(n \times m_j\) matrix of evaluations of the \(\psi_{j\ell}\) and for \(j = 1, \ldots, p\), i.e., \(\boldsymbol{\theta}_j\) is a \(m_j\)-dimensional column vector of basis coefficients for the \(j\)th main effect. In this article we consider an additive interaction regression model of the form \[\begin{align} Y & = \beta_0 \cdot \boldsymbol{1} + \sum_{j=1}^p \boldsymbol{\Psi}_j \boldsymbol{\theta}_j + \beta_E X_E + \sum_{j=1}^p (X_E \circ \boldsymbol{\Psi}_j) \boldsymbol{\alpha}_{j} + \varepsilon \label{eq:linpred} -\end{align}\] -where \(\beta_0\) is the intercept, \(\beta_E\) is the coefficient for the environment variable, \(\boldsymbol{\alpha}_j = (\alpha_{j1}, \ldots, \alpha_{jm_j})\in \mathbb{R}^{m_j}\) are the basis coefficients for the \(j\)th interaction term and \((X_E \circ \boldsymbol{\Psi}_j)\) is the \(n \times m_j\) matrix formed by the component-wise multiplication of the column vector \(X_E\) by each column of \(\boldsymbol{\Psi}_j\). To enforce the strong heredity property, we reparametrize the coefficients for the interaction terms in~ as \(\boldsymbol{\alpha}_{j} = \gamma_{j} \beta_E \boldsymbol{\theta}_j\): -\[\begin{align} +\end{align}\] where \(\beta_0\) is the intercept, \(\beta_E\) is the coefficient for the environment variable, \(\boldsymbol{\alpha}_j = (\alpha_{j1}, \ldots, \alpha_{jm_j})\in \mathbb{R}^{m_j}\) are the basis coefficients for the \(j\)th interaction term and \((X_E \circ \boldsymbol{\Psi}_j)\) is the \(n \times m_j\) matrix formed by the component-wise multiplication of the column vector \(X_E\) by each column of \(\boldsymbol{\Psi}_j\). To enforce the strong heredity property, we reparametrize the coefficients for the interaction terms in~ as \(\boldsymbol{\alpha}_{j} = \gamma_{j} \beta_E \boldsymbol{\theta}_j\): \[\begin{align} Y & = \beta_0 \cdot \boldsymbol{1} + \sum_{j=1}^p \boldsymbol{\Psi}_j \boldsymbol{\theta}_j + \beta_E X_E + \sum_{j=1}^p \gamma_{j} \beta_E (X_E \circ \boldsymbol{\Psi}_j) \boldsymbol{\theta}_j + \varepsilon \label{eq:linpred2} -\end{align}\] -For a continuous response, we use the squared-error loss: -\[\begin{equation} +\end{align}\] For a continuous response, we use the squared-error loss: \[\begin{equation} \mathcal{L}(Y;\boldsymbol{\theta}) = \frac{1}{2n}\lVert Y - \beta_0 \cdot \boldsymbol{1} - \sum_{j=1}^p \boldsymbol{\Psi}_j \boldsymbol{\theta}_j - \beta_E X_E - \sum_{j=1}^p \gamma_{j} \beta_E (X_E \circ \boldsymbol{\Psi}_j) \boldsymbol{\theta}_j \rVert_2^2 -\end{equation}\] -

where \(\boldsymbol{\theta} \equiv (\beta_0, \beta_E,\boldsymbol{\theta}_1, \ldots, \boldsymbol{\theta}_p, \gamma_1, \ldots, \gamma_p)\).

-We consider the following penalized least squares criterion for this problem: -\[\begin{equation} +\end{equation}\] where \(\boldsymbol{\theta} \equiv (\beta_0, \beta_E,\boldsymbol{\theta}_1, \ldots, \boldsymbol{\theta}_p, \gamma_1, \ldots, \gamma_p)\).

+

We consider the following penalized least squares criterion for this problem: \[\begin{equation} \arg\min_{\boldsymbol{\theta} } \mathcal{L}(Y;\boldsymbol{\theta}) + \lambda (1-\alpha) \left( w_E |\beta_E| + \sum_{j=1}^{p} w_j \lVert\boldsymbol{\theta}_j \rVert_2 \right) + \lambda\alpha \sum_{j=1}^{p} w_{jE} |\gamma_{j}| \label{eq:lassolikelihood3} -\end{equation}\] -

where \(\lambda >0\) and \(\alpha \in (0,1)\) are tuning parameters and \(w_E, w_j, w_{jE}\) are adaptive weights for \(j=1, \ldots, p\). These weights serve as a way of allowing parameters to be penalized differently.

+\end{equation}\]
where \(\lambda >0\) and \(\alpha \in (0,1)\) are tuning parameters and \(w_E, w_j, w_{jE}\) are adaptive weights for \(j=1, \ldots, p\). These weights serve as a way of allowing parameters to be penalized differently.

Installation

The package can be installed from GitHub via

-
install.packages("pacman")
-pacman::p_load_gh('sahirbhatnagar/sail')
+
install.packages("pacman")
+pacman::p_load_gh('sahirbhatnagar/sail')

Quick Start

We give a quick overview of the main functions and go into details in other vignettes. We will use the simulated data which ships with the package and can be loaded via:

-
library(sail)
-data("sailsim")
-names(sailsim)
-#> [1] "x"        "y"        "e"        "f1"       "f2"       "f3"      
-#> [7] "f4"       "f3.inter" "f4.inter"
-

We first define a basis expansion. In this example we use cubic bsplines with degree 5.

-
library(splines)
-f.basis <- function(x) splines::bs(x, degree = 5)
+ +

We first define a basis expansion. In this example we use cubic bsplines with degree 3.

+

Next we fit the model using the most basic call to sail

-
fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis)
+
fit <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis)

fit is an object of class sail that contains all the relevant information of the fitted model including the estimated coefficients at each value of \(\lambda\) (by default the program chooses its own decreasing sequence of 100 \(\lambda\) values). There are print, plot, coef and predict methods of objects of class sail. The print method outputs the following:

-
fit
-#> 
-#> Call:  sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis) 
-#> 
-#>      df_main df_interaction df_environment     %Dev  Lambda
-#> s1         0              0              0 0.000000 1.48800
-#> s2         0              0              1 0.001698 1.42100
-#> s3         0              0              1 0.003357 1.35600
-#> s4         0              0              1 0.004897 1.29400
-#> s5         0              0              1 0.006352 1.23500
-#> s6         1              0              1 0.014720 1.17900
-#> s7         2              0              1 0.045810 1.12600
-#> s8         2              0              1 0.080020 1.07500
-#> s9         2              0              1 0.111900 1.02600
-#> s10        2              0              1 0.141400 0.97910
-#> s11        2              0              1 0.168900 0.93460
-#> s12        2              0              1 0.194400 0.89210
-#> s13        2              0              1 0.218100 0.85160
-#> s14        2              0              1 0.240000 0.81290
-#> s15        2              0              1 0.260400 0.77590
-#> s16        2              0              1 0.279200 0.74070
-#> s17        3              1              1 0.465100 0.70700
-#> s18        3              1              1 0.479500 0.67490
-#> s19        3              1              1 0.492900 0.64420
-#> s20        3              2              1 0.508200 0.61490
-#> s21        3              2              1 0.524200 0.58700
-#> s22        3              2              1 0.536600 0.56030
-#> s23        3              2              1 0.548000 0.53480
-#> s24        4              2              1 0.558000 0.51050
-#> s25        5              2              1 0.568900 0.48730
-#> s26        5              2              1 0.579900 0.46520
-#> s27        5              2              1 0.590100 0.44400
-#> s28        5              2              1 0.599500 0.42380
-#> s29        5              3              1 0.609800 0.40460
-#> s30        5              3              1 0.619100 0.38620
-#> s31        5              3              1 0.628200 0.36860
-#> s32        6              3              1 0.637200 0.35190
-#> s33        6              3              1 0.646800 0.33590
-#> s34        6              3              1 0.655000 0.32060
-#> s35        6              3              1 0.663300 0.30600
-#> s36        7              3              1 0.671600 0.29210
-#> s37        7              3              1 0.679500 0.27890
-#> s38        7              3              1 0.687400 0.26620
-#> s39        7              3              1 0.694600 0.25410
-#> s40        7              4              1 0.702600 0.24250
-#> s41        7              4              1 0.734100 0.23150
-#> s42        7              4              1 0.739300 0.22100
-#> s43        7              5              1 0.745200 0.21090
-#> s44        7              6              1 0.754400 0.20140
-#> s45        7              6              1 0.760700 0.19220
-#> s46        7              6              1 0.767300 0.18350
-#> s47        7              6              1 0.771800 0.17510
-#> s48        7              6              1 0.776100 0.16720
-#> s49        8              6              1 0.780700 0.15960
-#> s50        8              6              1 0.784500 0.15230
-#> s51        9              6              1 0.788700 0.14540
-#> s52       10              6              1 0.792700 0.13880
-#> s53       12              6              1 0.797800 0.13250
-#> s54       13              6              1 0.802600 0.12650
-#> s55       13              6              1 0.807500 0.12070
-#> s56       13              6              1 0.812200 0.11520
-#> s57       14              6              1 0.816700 0.11000
-#> s58       14              6              1 0.821300 0.10500
-#> s59       15              6              1 0.826100 0.10020
-#> s60       15              7              1 0.831200 0.09566
-#> s61       13             10              1 0.871400 0.09131
-#> s62       13             10              1 0.873800 0.08716
-#> s63       13             10              1 0.876200 0.08320
-#> s64       14             10              1 0.878600 0.07942
-#> s65       14             10              1 0.881000 0.07581
-#> s66       14             11              1 0.883400 0.07236
-#> s67       14             11              1 0.885900 0.06907
-#> s68       14             11              1 0.888400 0.06593
-#> s69       14             11              1 0.890600 0.06294
-#> s70       16             13              1 0.930600 0.06008
-#> s71       16             13              1 0.932300 0.05735
-#> s72       16             13              1 0.934200 0.05474
-#> s73       16             13              1 0.936100 0.05225
-#> s74       16             13              1 0.938500 0.04988
-#> s75       16             13              1 0.940000 0.04761
-#> s76       17             13              1 0.942100 0.04545
-#> s77       17             13              1 0.943800 0.04338
-#> s78       17             14              1 0.945600 0.04141
-#> s79       17             14              1 0.947300 0.03953
-#> s80       18             14              1 0.949000 0.03773
-#> s81       18             14              1 0.950700 0.03602
-#> s82       18             14              1 0.952400 0.03438
-#> s83       18             14              1 0.954400 0.03282
-#> s84       18             14              1 0.955800 0.03132
-#> s85       18             14              1 0.957200 0.02990
-#> s86       19             14              1 0.959000 0.02854
-#> s87       19             15              1 0.960300 0.02724
-#> s88       19             15              1 0.967800 0.02601
-#> s89       19             15              1 0.968900 0.02482
-#> s90       19             15              1 0.970100 0.02370
-#> s91       19             15              1 0.971300 0.02262
-#> s92       19             15              1 0.972400 0.02159
-#> s93       19             15              1 0.973500 0.02061
-#> s94       19             15              1 0.974600 0.01967
-#> s95       20             19              1 0.977900 0.01878
-#> s96       20             19              1 0.978600 0.01792
-#> s97       20             19              1 0.979300 0.01711
-#> s98       20             19              1 0.980000 0.01633
-#> s99       20             19              1 0.980700 0.01559
-#> s100      20             19              1 0.981400 0.01488
+
fit
+#> 
+#> Call:  sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis) 
+#> 
+#>      df_main df_interaction df_environment     %Dev  Lambda
+#> s1         0              0              0 0.000000 1.48800
+#> s2         0              0              1 0.001701 1.42000
+#> s3         0              0              1 0.003359 1.35600
+#> s4         0              0              1 0.004899 1.29400
+#> s5         0              0              1 0.006354 1.23500
+#> s6         0              0              1 0.007728 1.17900
+#> s7         0              0              1 0.009028 1.12600
+#> s8         0              0              1 0.010260 1.07500
+#> s9         1              0              1 0.018970 1.02600
+#> s10        2              0              1 0.042490 0.97900
+#> s11        2              0              1 0.069000 0.93450
+#> s12        2              0              1 0.094110 0.89210
+#> s13        2              0              1 0.117900 0.85150
+#> s14        2              0              1 0.140500 0.81280
+#> s15        3              0              1 0.163800 0.77590
+#> s16        4              0              1 0.189100 0.74060
+#> s17        4              0              1 0.214000 0.70690
+#> s18        5              0              1 0.238100 0.67480
+#> s19        5              0              1 0.262200 0.64410
+#> s20        3              1              1 0.439100 0.61490
+#> s21        4              2              1 0.457000 0.58690
+#> s22        5              2              1 0.475400 0.56020
+#> s23        5              2              1 0.491600 0.53480
+#> s24        5              2              1 0.505300 0.51050
+#> s25        5              2              1 0.518200 0.48730
+#> s26        5              2              1 0.530100 0.46510
+#> s27        5              2              1 0.541200 0.44400
+#> s28        5              2              1 0.551400 0.42380
+#> s29        5              2              1 0.561400 0.40450
+#> s30        5              2              1 0.569300 0.38620
+#> s31        5              2              1 0.577300 0.36860
+#> s32        6              2              1 0.585500 0.35190
+#> s33        6              2              1 0.594900 0.33590
+#> s34        6              2              1 0.603700 0.32060
+#> s35        7              3              1 0.612300 0.30600
+#> s36        7              3              1 0.620400 0.29210
+#> s37        8              4              1 0.629200 0.27880
+#> s38        8              4              1 0.641900 0.26620
+#> s39        9              4              1 0.650000 0.25410
+#> s40        9              4              1 0.658500 0.24250
+#> s41        8              4              1 0.689000 0.23150
+#> s42        8              4              1 0.695300 0.22100
+#> s43        8              4              1 0.701400 0.21090
+#> s44        9              4              1 0.707200 0.20130
+#> s45        8              6              1 0.728900 0.19220
+#> s46        8              6              1 0.733700 0.18350
+#> s47        8              6              1 0.738200 0.17510
+#> s48        8              7              1 0.742400 0.16720
+#> s49        9              7              1 0.747600 0.15960
+#> s50       10              7              1 0.752100 0.15230
+#> s51       10              7              1 0.756500 0.14540
+#> s52       10              7              1 0.760900 0.13880
+#> s53       11              7              1 0.765200 0.13250
+#> s54       11              7              1 0.769900 0.12640
+#> s55       11              7              1 0.773900 0.12070
+#> s56       11              7              1 0.778100 0.11520
+#> s57       12              9              1 0.794000 0.11000
+#> s58       12              9              1 0.798500 0.10500
+#> s59       12              9              1 0.802700 0.10020
+#> s60       12              9              1 0.806600 0.09565
+#> s61       13              9              1 0.810400 0.09131
+#> s62       13              9              1 0.814100 0.08716
+#> s63       13              9              1 0.817200 0.08319
+#> s64       16              9              1 0.820000 0.07941
+#> s65       16              9              1 0.822900 0.07580
+#> s66       16              9              1 0.825600 0.07236
+#> s67       16              9              1 0.828200 0.06907
+#> s68       16              9              1 0.830700 0.06593
+#> s69       17             10              1 0.833500 0.06293
+#> s70       17             10              1 0.840000 0.06007
+#> s71       16             12              1 0.849000 0.05734
+#> s72       16             12              1 0.851400 0.05474
+#> s73       18             12              1 0.853900 0.05225
+#> s74       19             12              1 0.856700 0.04987
+#> s75       19             12              1 0.859600 0.04761
+#> s76       19             12              1 0.862600 0.04544
+#> s77       19             15              1 0.897700 0.04338
+#> s78       20             18              1 0.907600 0.04141
+#> s79       20             18              1 0.909800 0.03952
+#> s80       20             19              1 0.925800 0.03773
+#> s81       20             20              1 0.927700 0.03601
+#> s82       20             20              1 0.929700 0.03438
+#> s83       20             20              1 0.931800 0.03281
+#> s84       20             20              1 0.934500 0.03132
+#> s85       20             20              1 0.936100 0.02990
+#> s86       20             20              1 0.937700 0.02854
+#> s87       20             20              1 0.939300 0.02724
+#> s88       20             20              1 0.943900 0.02600
+#> s89       20             20              1 0.944700 0.02482
+#> s90       20             20              1 0.945600 0.02369
+#> s91       20             20              1 0.946500 0.02262
+#> s92       20             20              1 0.947100 0.02159
+#> s93       20             20              1 0.948500 0.02061
+#> s94       20             20              1 0.949200 0.01967
+#> s95       20             20              1 0.950100 0.01878
+#> s96       20             20              1 0.950700 0.01792
+#> s97       20             20              1 0.951400 0.01711
+#> s98       20             20              1 0.952000 0.01633
+#> s99       20             20              1 0.952600 0.01559
+#> s100      20             20              1 0.954900 0.01488

When expand = TRUE (i.e. the user did not provide their own design matrix), the df_main and df_interaction columns correspond to the number of non-zero predictors present in the model before basis expansion. This does not correspond to the number of non-zero coefficients in the model, but rather the number of unique variables. In this example we expanded each column of \(\mathbf{X}\) to five columns. If df_main=4, df_interaction=2 and df_environment=1, then the total number of non-zero coefficients would be \(5 \times (4+2) + 1\).

The entire solution path can be plotted via the plot method for objects of class sail. The y-axis is the value of the coefficient and the x-axis is the \(\log(\lambda)\). Each line represents a coefficient in the model, and each color represents a variable (i.e. in this example a given variable will have 5 lines when it is non-zero). The numbers at the top of the plot represent the number of non-zero variables in the model: top panel (df_main + df_environment), bottom panel (df_interaction). The black line is the coefficient path for the environment variable.

-
plot(fit)
+
plot(fit)

The estimated coefficients at each value of lambda is given by (matrix partially printed here for brevity)

-
coef(fit)[1:6,50:55]
-#> 6 x 6 sparse Matrix of class "dgCMatrix"
-#>                   s50        s51        s52        s53        s54
-#> (Intercept)  5.290833  5.2837573  5.2803780  5.2753630  5.2717902
-#> X1_1        -0.979303 -0.9604292 -0.9449933 -0.9220866 -0.9171202
-#> X1_2         1.690176  1.7893506  1.8923047  1.9950535  2.1040903
-#> X1_3         1.646209  1.7048994  1.7722054  1.8250656  1.8950572
-#> X1_4         1.522426  1.5433270  1.5662846  1.5853967  1.6101828
-#> X1_5         3.338527  3.4182125  3.4907005  3.5762497  3.6632614
-#>                    s55
-#> (Intercept)  5.2695429
-#> X1_1        -0.9270781
-#> X1_2         2.2057013
-#> X1_3         1.9641879
-#> X1_4         1.6321740
-#> X1_5         3.7452560
+

The predicted response at each value of lambda:

-
predict(fit)[1:5,50:55]
-#>            s50       s51       s52       s53       s54       s55
-#> [1,]  6.244760  6.199363  6.185411  6.178014  6.156219  6.124321
-#> [2,]  3.002808  2.995389  3.038672  3.079610  3.143616  3.208972
-#> [3,]  2.073350  2.043516  2.016354  1.997213  1.966913  1.957284
-#> [4,] 13.489022 13.490853 13.361077 13.384407 13.350715 13.324150
-#> [5,]  1.225603  1.210385  1.134488  1.156340  1.156697  1.156134
+

The predicted response at a specific value of lambda can be specified by the s argument:

-
predict(fit, s = 0.8)
-#>               1
-#>   [1,] 5.624232
-#>   [2,] 4.940944
-#>   [3,] 3.847965
-#>   [4,] 6.687777
-#>   [5,] 3.058124
-#>   [6,] 3.607326
-#>   [7,] 6.615916
-#>   [8,] 5.032047
-#>   [9,] 6.040452
-#>  [10,] 5.486751
-#>  [11,] 4.765237
-#>  [12,] 7.238408
-#>  [13,] 7.063706
-#>  [14,] 4.590884
-#>  [15,] 7.657128
-#>  [16,] 4.904077
-#>  [17,] 4.195213
-#>  [18,] 4.504339
-#>  [19,] 4.809399
-#>  [20,] 5.615791
-#>  [21,] 6.546767
-#>  [22,] 5.673886
-#>  [23,] 4.631122
-#>  [24,] 6.849338
-#>  [25,] 4.091877
-#>  [26,] 7.020022
-#>  [27,] 7.175685
-#>  [28,] 3.550668
-#>  [29,] 6.737500
-#>  [30,] 6.366243
-#>  [31,] 5.192395
-#>  [32,] 5.384846
-#>  [33,] 6.935418
-#>  [34,] 4.258696
-#>  [35,] 7.603471
-#>  [36,] 5.303784
-#>  [37,] 5.303826
-#>  [38,] 4.285530
-#>  [39,] 4.803300
-#>  [40,] 5.503811
-#>  [41,] 3.620280
-#>  [42,] 3.628351
-#>  [43,] 5.421528
-#>  [44,] 7.492914
-#>  [45,] 4.183416
-#>  [46,] 4.536360
-#>  [47,] 5.348853
-#>  [48,] 7.518597
-#>  [49,] 4.493770
-#>  [50,] 5.276594
-#>  [51,] 5.568093
-#>  [52,] 4.473407
-#>  [53,] 5.563292
-#>  [54,] 5.744353
-#>  [55,] 4.592868
-#>  [56,] 4.307980
-#>  [57,] 4.854115
-#>  [58,] 5.244134
-#>  [59,] 6.736890
-#>  [60,] 5.070075
-#>  [61,] 4.517567
-#>  [62,] 3.129270
-#>  [63,] 6.601207
-#>  [64,] 4.547151
-#>  [65,] 4.566028
-#>  [66,] 6.376860
-#>  [67,] 4.967343
-#>  [68,] 6.138383
-#>  [69,] 5.385448
-#>  [70,] 6.923559
-#>  [71,] 5.015826
-#>  [72,] 3.524949
-#>  [73,] 5.669353
-#>  [74,] 7.044308
-#>  [75,] 3.523070
-#>  [76,] 4.674963
-#>  [77,] 3.396258
-#>  [78,] 5.592357
-#>  [79,] 5.415423
-#>  [80,] 4.810314
-#>  [81,] 5.712646
-#>  [82,] 5.990818
-#>  [83,] 4.861425
-#>  [84,] 6.761552
-#>  [85,] 5.493592
-#>  [86,] 3.607781
-#>  [87,] 3.986110
-#>  [88,] 4.259476
-#>  [89,] 4.174571
-#>  [90,] 3.666310
-#>  [91,] 5.181711
-#>  [92,] 7.086435
-#>  [93,] 5.406326
-#>  [94,] 6.583031
-#>  [95,] 4.664773
-#>  [96,] 3.695451
-#>  [97,] 5.100857
-#>  [98,] 4.984838
-#>  [99,] 3.961504
-#> [100,] 6.078087
+
predict(fit, s = 0.8)
+#>               1
+#>   [1,] 5.565188
+#>   [2,] 5.245648
+#>   [3,] 4.256588
+#>   [4,] 6.314703
+#>   [5,] 3.884374
+#>   [6,] 4.446973
+#>   [7,] 6.112132
+#>   [8,] 5.360375
+#>   [9,] 5.972536
+#>  [10,] 5.558947
+#>  [11,] 5.252652
+#>  [12,] 6.394977
+#>  [13,] 6.304268
+#>  [14,] 4.993944
+#>  [15,] 6.673554
+#>  [16,] 4.852025
+#>  [17,] 5.011305
+#>  [18,] 4.855807
+#>  [19,] 5.182772
+#>  [20,] 5.292666
+#>  [21,] 5.939055
+#>  [22,] 5.624398
+#>  [23,] 4.496055
+#>  [24,] 6.156093
+#>  [25,] 4.839130
+#>  [26,] 6.202291
+#>  [27,] 6.240929
+#>  [28,] 4.440300
+#>  [29,] 6.173744
+#>  [30,] 5.779888
+#>  [31,] 5.060847
+#>  [32,] 5.034286
+#>  [33,] 6.319719
+#>  [34,] 4.387120
+#>  [35,] 6.716587
+#>  [36,] 5.668114
+#>  [37,] 5.065923
+#>  [38,] 4.961400
+#>  [39,] 5.008489
+#>  [40,] 5.146974
+#>  [41,] 3.696416
+#>  [42,] 4.303783
+#>  [43,] 5.580174
+#>  [44,] 6.591266
+#>  [45,] 4.633462
+#>  [46,] 4.522579
+#>  [47,] 5.633387
+#>  [48,] 6.633019
+#>  [49,] 5.013153
+#>  [50,] 5.267268
+#>  [51,] 5.035807
+#>  [52,] 4.611586
+#>  [53,] 5.341352
+#>  [54,] 5.233311
+#>  [55,] 4.733031
+#>  [56,] 5.022145
+#>  [57,] 5.299347
+#>  [58,] 5.187987
+#>  [59,] 6.093533
+#>  [60,] 5.332161
+#>  [61,] 4.536252
+#>  [62,] 3.800441
+#>  [63,] 6.222930
+#>  [64,] 4.917357
+#>  [65,] 5.080531
+#>  [66,] 5.868890
+#>  [67,] 4.541408
+#>  [68,] 5.701353
+#>  [69,] 5.271430
+#>  [70,] 6.208581
+#>  [71,] 4.813133
+#>  [72,] 4.031251
+#>  [73,] 5.693444
+#>  [74,] 6.269703
+#>  [75,] 4.328094
+#>  [76,] 5.015667
+#>  [77,] 4.140977
+#>  [78,] 5.788631
+#>  [79,] 5.137175
+#>  [80,] 5.144183
+#>  [81,] 5.533654
+#>  [82,] 5.638968
+#>  [83,] 5.349115
+#>  [84,] 5.995233
+#>  [85,] 4.787946
+#>  [86,] 4.485989
+#>  [87,] 4.589191
+#>  [88,] 5.084970
+#>  [89,] 4.414470
+#>  [90,] 3.896057
+#>  [91,] 5.675552
+#>  [92,] 6.268628
+#>  [93,] 5.593670
+#>  [94,] 5.971994
+#>  [95,] 5.096703
+#>  [96,] 4.168302
+#>  [97,] 5.017025
+#>  [98,] 5.368094
+#>  [99,] 4.576291
+#> [100,] 5.764786

You can specify more than one value for s:

-
predict(fit, s = c(0.8, 0.2))
-#>               1          2
-#>   [1,] 5.624232  6.5230740
-#>   [2,] 4.940944  2.9750177
-#>   [3,] 3.847965  2.3266980
-#>   [4,] 6.687777 13.9562204
-#>   [5,] 3.058124  1.5688962
-#>   [6,] 3.607326  1.6348912
-#>   [7,] 6.615916 13.2009227
-#>   [8,] 5.032047  5.9480404
-#>   [9,] 6.040452  5.8691675
-#>  [10,] 5.486751  5.0987940
-#>  [11,] 4.765237  3.5631269
-#>  [12,] 7.238408 11.8329816
-#>  [13,] 7.063706 12.4826512
-#>  [14,] 4.590884  3.9524402
-#>  [15,] 7.657128 14.2931482
-#>  [16,] 4.904077  5.0900767
-#>  [17,] 4.195213 -0.5844299
-#>  [18,] 4.504339  4.4666357
-#>  [19,] 4.809399  3.0374049
-#>  [20,] 5.615791  3.5399188
-#>  [21,] 6.546767  8.3512494
-#>  [22,] 5.673886  4.7077896
-#>  [23,] 4.631122  1.9943630
-#>  [24,] 6.849338 10.7983805
-#>  [25,] 4.091877  0.9601846
-#>  [26,] 7.020022  9.3762352
-#>  [27,] 7.175685  8.6775432
-#>  [28,] 3.550668 -1.6523278
-#>  [29,] 6.737500 13.5513436
-#>  [30,] 6.366243  2.2204467
-#>  [31,] 5.192395  5.8213763
-#>  [32,] 5.384846  7.4511268
-#>  [33,] 6.935418  9.0277752
-#>  [34,] 4.258696  4.5323823
-#>  [35,] 7.603471 16.3907390
-#>  [36,] 5.303784  0.1377432
-#>  [37,] 5.303826  5.6261096
-#>  [38,] 4.285530  2.3206999
-#>  [39,] 4.803300  3.8195444
-#>  [40,] 5.503811  4.8408086
-#>  [41,] 3.620280  2.4050059
-#>  [42,] 3.628351  0.4144305
-#>  [43,] 5.421528  6.4970752
-#>  [44,] 7.492914 15.6998648
-#>  [45,] 4.183416  3.1368088
-#>  [46,] 4.536360  3.5137943
-#>  [47,] 5.348853  4.4711267
-#>  [48,] 7.518597 18.0122252
-#>  [49,] 4.493770  2.3526655
-#>  [50,] 5.276594  7.4618284
-#>  [51,] 5.568093  5.9679862
-#>  [52,] 4.473407  1.7229550
-#>  [53,] 5.563292  7.3990744
-#>  [54,] 5.744353  8.6534271
-#>  [55,] 4.592868  2.0907568
-#>  [56,] 4.307980  0.7927840
-#>  [57,] 4.854115  5.3436578
-#>  [58,] 5.244134  9.2910545
-#>  [59,] 6.736890  9.7709887
-#>  [60,] 5.070075  1.6897955
-#>  [61,] 4.517567  1.4507809
-#>  [62,] 3.129270 -0.9532221
-#>  [63,] 6.601207  8.1123225
-#>  [64,] 4.547151  1.3003285
-#>  [65,] 4.566028  3.1206603
-#>  [66,] 6.376860  3.5765440
-#>  [67,] 4.967343  4.8268433
-#>  [68,] 6.138383  6.1849972
-#>  [69,] 5.385448 10.1092482
-#>  [70,] 6.923559  8.2999571
-#>  [71,] 5.015826  4.0040478
-#>  [72,] 3.524949  1.3597820
-#>  [73,] 5.669353  6.7846103
-#>  [74,] 7.044308  4.5323126
-#>  [75,] 3.523070  2.6555577
-#>  [76,] 4.674963  1.1032379
-#>  [77,] 3.396258  1.8733145
-#>  [78,] 5.592357 13.3777530
-#>  [79,] 5.415423  6.6235012
-#>  [80,] 4.810314  2.9584783
-#>  [81,] 5.712646  4.0235765
-#>  [82,] 5.990818  4.9867095
-#>  [83,] 4.861425  4.5053610
-#>  [84,] 6.761552  5.9701019
-#>  [85,] 5.493592  4.8052874
-#>  [86,] 3.607781  1.8020652
-#>  [87,] 3.986110  3.4415117
-#>  [88,] 4.259476  0.7337290
-#>  [89,] 4.174571  4.3173319
-#>  [90,] 3.666310  5.4733594
-#>  [91,] 5.181711  8.2829841
-#>  [92,] 7.086435 10.2504954
-#>  [93,] 5.406326  5.2240663
-#>  [94,] 6.583031  7.7020652
-#>  [95,] 4.664773  5.3974401
-#>  [96,] 3.695451  2.1516883
-#>  [97,] 5.100857  9.2733043
-#>  [98,] 4.984838  6.5142889
-#>  [99,] 3.961504  3.3387104
-#> [100,] 6.078087  4.9794667
+
predict(fit, s = c(0.8, 0.2))
+#>               1          2
+#>   [1,] 5.565188  6.4563490
+#>   [2,] 5.245648  3.5762830
+#>   [3,] 4.256588  1.2541443
+#>   [4,] 6.314703 12.3815143
+#>   [5,] 3.884374  1.5612304
+#>   [6,] 4.446973  1.5503816
+#>   [7,] 6.112132 12.6330145
+#>   [8,] 5.360375  6.4671028
+#>   [9,] 5.972536  7.0190070
+#>  [10,] 5.558947  5.2948898
+#>  [11,] 5.252652  4.3677887
+#>  [12,] 6.394977 11.2278283
+#>  [13,] 6.304268 11.6189806
+#>  [14,] 4.993944  4.0124434
+#>  [15,] 6.673554 14.4290841
+#>  [16,] 4.852025  5.0443558
+#>  [17,] 5.011305  0.8168762
+#>  [18,] 4.855807  4.5902225
+#>  [19,] 5.182772  3.1477565
+#>  [20,] 5.292666  3.4902000
+#>  [21,] 5.939055  8.4361272
+#>  [22,] 5.624398  4.6555593
+#>  [23,] 4.496055  1.7045694
+#>  [24,] 6.156093 10.5558726
+#>  [25,] 4.839130  1.2444600
+#>  [26,] 6.202291  8.6260313
+#>  [27,] 6.240929  7.7126054
+#>  [28,] 4.440300 -0.7778888
+#>  [29,] 6.173744 12.0720146
+#>  [30,] 5.779888  1.8831854
+#>  [31,] 5.060847  4.9276303
+#>  [32,] 5.034286  8.3934198
+#>  [33,] 6.319719  8.9647247
+#>  [34,] 4.387120  3.6730133
+#>  [35,] 6.716587 15.4640443
+#>  [36,] 5.668114  1.1145380
+#>  [37,] 5.065923  5.0030880
+#>  [38,] 4.961400  3.0886490
+#>  [39,] 5.008489  3.5325687
+#>  [40,] 5.146974  4.7369669
+#>  [41,] 3.696416  1.7665100
+#>  [42,] 4.303783  0.7109199
+#>  [43,] 5.580174  6.8465242
+#>  [44,] 6.591266 14.7008154
+#>  [45,] 4.633462  2.1878324
+#>  [46,] 4.522579  3.8488986
+#>  [47,] 5.633387  6.2435977
+#>  [48,] 6.633019 16.8729068
+#>  [49,] 5.013153  3.0090785
+#>  [50,] 5.267268  7.7524439
+#>  [51,] 5.035807  5.7762293
+#>  [52,] 4.611586  1.7242234
+#>  [53,] 5.341352  7.2133769
+#>  [54,] 5.233311  8.9233017
+#>  [55,] 4.733031  2.0904075
+#>  [56,] 5.022145  1.2321963
+#>  [57,] 5.299347  5.5841592
+#>  [58,] 5.187987  8.1850179
+#>  [59,] 6.093533  9.1272205
+#>  [60,] 5.332161  2.6762385
+#>  [61,] 4.536252  1.2714320
+#>  [62,] 3.800441 -0.7821244
+#>  [63,] 6.222930  9.0399619
+#>  [64,] 4.917357  1.4590598
+#>  [65,] 5.080531  3.3498113
+#>  [66,] 5.868890  3.2462364
+#>  [67,] 4.541408  3.8775236
+#>  [68,] 5.701353  5.9176470
+#>  [69,] 5.271430  9.4635363
+#>  [70,] 6.208581  8.5531857
+#>  [71,] 4.813133  3.1399498
+#>  [72,] 4.031251  0.8587915
+#>  [73,] 5.693444  7.2551243
+#>  [74,] 6.269703  4.7373189
+#>  [75,] 4.328094  2.7418860
+#>  [76,] 5.015667  1.4436768
+#>  [77,] 4.140977  2.3070947
+#>  [78,] 5.788631 16.4559530
+#>  [79,] 5.137175  7.0246294
+#>  [80,] 5.144183  2.3912821
+#>  [81,] 5.533654  4.2128178
+#>  [82,] 5.638968  4.5853076
+#>  [83,] 5.349115  5.3680719
+#>  [84,] 5.995233  5.6151668
+#>  [85,] 4.787946  3.5272371
+#>  [86,] 4.485989  2.9988064
+#>  [87,] 4.589191  3.5070799
+#>  [88,] 5.084970  1.7410672
+#>  [89,] 4.414470  4.7618966
+#>  [90,] 3.896057  5.6814850
+#>  [91,] 5.675552  8.0216272
+#>  [92,] 6.268628  9.1200249
+#>  [93,] 5.593670  4.7429260
+#>  [94,] 5.971994  7.6268458
+#>  [95,] 5.096703  5.7827835
+#>  [96,] 4.168302  2.7426953
+#>  [97,] 5.017025  9.8201852
+#>  [98,] 5.368094  6.1535859
+#>  [99,] 4.576291  3.9789271
+#> [100,] 5.764786  4.7680511

You can also extract a list of active variables (i.e. variables with a non-zero estimated coefficient) for each value of lambda:

-
fit[["active"]]
-#> [[1]]
-#> character(0)
-#> 
-#> [[2]]
-#> [1] "E"
-#> 
-#> [[3]]
-#> [1] "E"
-#> 
-#> [[4]]
-#> [1] "E"
-#> 
-#> [[5]]
-#> [1] "E"
-#> 
-#> [[6]]
-#> [1] "X4" "E" 
-#> 
-#> [[7]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[8]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[9]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[10]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[11]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[12]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[13]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[14]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[15]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[16]]
-#> [1] "X3" "X4" "E" 
-#> 
-#> [[17]]
-#> [1] "X1"   "X3"   "X4"   "X4:E" "E"   
-#> 
-#> [[18]]
-#> [1] "X1"   "X3"   "X4"   "X4:E" "E"   
-#> 
-#> [[19]]
-#> [1] "X1"   "X3"   "X4"   "X4:E" "E"   
-#> 
-#> [[20]]
-#> [1] "X1"   "X3"   "X4"   "X3:E" "X4:E" "E"   
-#> 
-#> [[21]]
-#> [1] "X1"   "X3"   "X4"   "X3:E" "X4:E" "E"   
-#> 
-#> [[22]]
-#> [1] "X1"   "X3"   "X4"   "X3:E" "X4:E" "E"   
-#> 
-#> [[23]]
-#> [1] "X1"   "X3"   "X4"   "X3:E" "X4:E" "E"   
-#> 
-#> [[24]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X3:E" "X4:E" "E"   
-#> 
-#> [[25]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
-#> 
-#> [[26]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
-#> 
-#> [[27]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
-#> 
-#> [[28]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
-#> 
-#> [[29]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[30]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[31]]
-#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[32]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[33]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[34]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[35]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X1:E" "X3:E" "X4:E" "E"   
-#> 
-#> [[36]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X3:E" "X4:E"
-#> [11] "E"   
-#> 
-#> [[37]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X3:E" "X4:E"
-#> [11] "E"   
-#> 
-#> [[38]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X3:E" "X4:E"
-#> [11] "E"   
-#> 
-#> [[39]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X3:E" "X4:E"
-#> [11] "E"   
-#> 
-#> [[40]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X2:E" "X3:E"
-#> [11] "X4:E" "E"   
-#> 
-#> [[41]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X2:E" "X3:E"
-#> [11] "X4:E" "E"   
-#> 
-#> [[42]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X2:E" "X3:E"
-#> [11] "X4:E" "E"   
-#> 
-#> [[43]]
-#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X20"  "X1:E" "X2:E" "X3:E"
-#> [11] "X4:E" "X8:E" "E"   
-#> 
-#> [[44]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X20"   "X1:E" 
-#>  [9] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[45]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X20"   "X1:E" 
-#>  [9] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[46]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X20"   "X1:E" 
-#>  [9] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[47]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X20"   "X1:E" 
-#>  [9] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[48]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X20"   "X1:E" 
-#>  [9] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[49]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X10"   "X11"   "X20"  
-#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[50]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X10"   "X11"   "X20"  
-#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[51]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
-#>  [9] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[52]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
-#>  [9] "X16"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E"
-#> [17] "E"    
-#> 
-#> [[53]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
-#>  [9] "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [17] "X8:E"  "X11:E" "E"    
-#> 
-#> [[54]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[55]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[56]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[57]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X14"   "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[58]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X14"   "X15"   "X16"   "X19"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[59]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X14"   "X15"   "X16"   "X17"   "X19"   "X20"   "X1:E" 
-#> [17] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "E"    
-#> 
-#> [[60]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
-#>  [9] "X11"   "X14"   "X15"   "X16"   "X17"   "X19"   "X20"   "X1:E" 
-#> [17] "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "X16:E" "E"    
-#> 
-#> [[61]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X15"   "X16"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E" "E"    
-#> 
-#> [[62]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X15"   "X16"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E" "E"    
-#> 
-#> [[63]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X15"   "X16"   "X20"   "X1:E"  "X2:E"  "X3:E" 
-#> [17] "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E" "E"    
-#> 
-#> [[64]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "E"    
-#> 
-#> [[65]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "E"    
-#> 
-#> [[66]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "X20:E" "E"    
-#> 
-#> [[67]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "X20:E" "E"    
-#> 
-#> [[68]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "X20:E" "E"    
-#> 
-#> [[69]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X15"   "X16"   "X20"   "X1:E"  "X2:E" 
-#> [17] "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E"  "X11:E" "X16:E"
-#> [25] "X20:E" "E"    
-#> 
-#> [[70]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[71]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[72]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[73]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[74]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[75]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
-#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X20"  
-#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
-#> [25] "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[76]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E" 
-#> [25] "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[77]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E" 
-#> [25] "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "E"    
-#> 
-#> [[78]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E" 
-#> [25] "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E" "E"    
-#> 
-#> [[79]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E" 
-#> [25] "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E" "E"    
-#> 
-#> [[80]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[81]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[82]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[83]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[84]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[85]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"  
-#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
-#> [25] "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E" "X20:E"
-#> [33] "E"    
-#> 
-#> [[86]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E" "X16:E"
-#> [33] "X20:E" "E"    
-#> 
-#> [[87]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[88]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[89]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[90]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[91]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[92]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[93]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[94]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
-#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X11:E" "X12:E" "X14:E" "X15:E"
-#> [33] "X16:E" "X20:E" "E"    
-#> 
-#> [[95]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"    
-#> 
-#> [[96]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"    
-#> 
-#> [[97]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"    
-#> 
-#> [[98]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"    
-#> 
-#> [[99]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"    
-#> 
-#> [[100]]
-#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
-#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
-#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
-#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
-#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X18:E" "X19:E" "X20:E" "E"
+
fit[["active"]]
+#> [[1]]
+#> character(0)
+#> 
+#> [[2]]
+#> [1] "E"
+#> 
+#> [[3]]
+#> [1] "E"
+#> 
+#> [[4]]
+#> [1] "E"
+#> 
+#> [[5]]
+#> [1] "E"
+#> 
+#> [[6]]
+#> [1] "E"
+#> 
+#> [[7]]
+#> [1] "E"
+#> 
+#> [[8]]
+#> [1] "E"
+#> 
+#> [[9]]
+#> [1] "X3" "E" 
+#> 
+#> [[10]]
+#> [1] "X3" "X4" "E" 
+#> 
+#> [[11]]
+#> [1] "X3" "X4" "E" 
+#> 
+#> [[12]]
+#> [1] "X3" "X4" "E" 
+#> 
+#> [[13]]
+#> [1] "X3" "X4" "E" 
+#> 
+#> [[14]]
+#> [1] "X3" "X4" "E" 
+#> 
+#> [[15]]
+#> [1] "X1" "X3" "X4" "E" 
+#> 
+#> [[16]]
+#> [1] "X1" "X3" "X4" "X8" "E" 
+#> 
+#> [[17]]
+#> [1] "X1" "X3" "X4" "X8" "E" 
+#> 
+#> [[18]]
+#> [1] "X1"  "X3"  "X4"  "X8"  "X11" "E"  
+#> 
+#> [[19]]
+#> [1] "X1"  "X3"  "X4"  "X8"  "X11" "E"  
+#> 
+#> [[20]]
+#> [1] "X1"   "X3"   "X4"   "X4:E" "E"   
+#> 
+#> [[21]]
+#> [1] "X1"   "X3"   "X4"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[22]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[23]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[24]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[25]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[26]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[27]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[28]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[29]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[30]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[31]]
+#> [1] "X1"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[32]]
+#> [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[33]]
+#> [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[34]]
+#> [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X3:E" "X4:E" "E"   
+#> 
+#> [[35]]
+#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X14"  "X1:E" "X3:E" "X4:E"
+#> [11] "E"   
+#> 
+#> [[36]]
+#>  [1] "X1"   "X2"   "X3"   "X4"   "X8"   "X11"  "X14"  "X1:E" "X3:E" "X4:E"
+#> [11] "E"   
+#> 
+#> [[37]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X14"   "X16"  
+#>  [9] "X1:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[38]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X14"   "X16"  
+#>  [9] "X1:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[39]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X14"   "X16"  
+#>  [9] "X20"   "X1:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[40]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X14"   "X16"  
+#>  [9] "X20"   "X1:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[41]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X2:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[42]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X2:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[43]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X2:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[44]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X14"   "X16"  
+#>  [9] "X20"   "X2:E"  "X3:E"  "X4:E"  "X11:E" "E"    
+#> 
+#> [[45]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X11:E" "X16:E" "E"    
+#> 
+#> [[46]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X11:E" "X16:E" "E"    
+#> 
+#> [[47]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X11:E" "X16:E" "E"    
+#> 
+#> [[48]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X8"    "X11"   "X16"   "X20"  
+#>  [9] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "X16:E" "E"    
+#> 
+#> [[49]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X16"  
+#>  [9] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E" "X16:E"
+#> [17] "E"    
+#> 
+#> [[50]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E"
+#> [17] "X16:E" "E"    
+#> 
+#> [[51]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E"
+#> [17] "X16:E" "E"    
+#> 
+#> [[52]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E"  "X11:E"
+#> [17] "X16:E" "E"    
+#> 
+#> [[53]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E" 
+#> [17] "X11:E" "X16:E" "E"    
+#> 
+#> [[54]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E" 
+#> [17] "X11:E" "X16:E" "E"    
+#> 
+#> [[55]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E" 
+#> [17] "X11:E" "X16:E" "E"    
+#> 
+#> [[56]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X11"   "X14"  
+#>  [9] "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X8:E" 
+#> [17] "X11:E" "X16:E" "E"    
+#> 
+#> [[57]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
+#>  [9] "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [17] "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[58]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
+#>  [9] "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [17] "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[59]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
+#>  [9] "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [17] "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[60]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X6"    "X8"    "X10"   "X11"  
+#>  [9] "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [17] "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[61]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
+#>  [9] "X11"   "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
+#> [17] "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[62]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
+#>  [9] "X11"   "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
+#> [17] "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[63]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X10"  
+#>  [9] "X11"   "X14"   "X16"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E" 
+#> [17] "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[64]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E"
+#> [25] "X20:E" "E"    
+#> 
+#> [[65]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E"
+#> [25] "X20:E" "E"    
+#> 
+#> [[66]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E"
+#> [25] "X20:E" "E"    
+#> 
+#> [[67]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E"
+#> [25] "X20:E" "E"    
+#> 
+#> [[68]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X11:E" "X16:E"
+#> [25] "X20:E" "E"    
+#> 
+#> [[69]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X19"  
+#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X9:E" 
+#> [25] "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[70]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X12"   "X14"   "X15"   "X16"   "X18"   "X19"  
+#> [17] "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X6:E"  "X8:E"  "X9:E" 
+#> [25] "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[71]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X14"   "X15"   "X16"   "X18"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
+#> [25] "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[72]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X8"    "X9"   
+#>  [9] "X10"   "X11"   "X14"   "X15"   "X16"   "X18"   "X19"   "X20"  
+#> [17] "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E"  "X8:E"  "X9:E" 
+#> [25] "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[73]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X13"   "X14"   "X15"   "X16"   "X18"  
+#> [17] "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E"  "X6:E" 
+#> [25] "X8:E"  "X9:E"  "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[74]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
+#> [25] "X6:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[75]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
+#> [25] "X6:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[76]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
+#> [25] "X6:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X16:E" "X20:E" "E"    
+#> 
+#> [[77]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X15"   "X16"   "X17"  
+#> [17] "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E"  "X5:E" 
+#> [25] "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X12:E" "X13:E" "X16:E"
+#> [33] "X19:E" "X20:E" "E"    
+#> 
+#> [[78]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E" "E"    
+#> 
+#> [[79]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E" "E"    
+#> 
+#> [[80]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X19:E" "X20:E" "E"    
+#> 
+#> [[81]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[82]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[83]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[84]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[85]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[86]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[87]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[88]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[89]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[90]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[91]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[92]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[93]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[94]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[95]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[96]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[97]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[98]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[99]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"    
+#> 
+#> [[100]]
+#>  [1] "X1"    "X2"    "X3"    "X4"    "X5"    "X6"    "X7"    "X8"   
+#>  [9] "X9"    "X10"   "X11"   "X12"   "X13"   "X14"   "X15"   "X16"  
+#> [17] "X17"   "X18"   "X19"   "X20"   "X1:E"  "X2:E"  "X3:E"  "X4:E" 
+#> [25] "X5:E"  "X6:E"  "X7:E"  "X8:E"  "X9:E"  "X10:E" "X11:E" "X12:E"
+#> [33] "X13:E" "X14:E" "X15:E" "X16:E" "X17:E" "X18:E" "X19:E" "X20:E"
+#> [41] "E"

Cross-Validation

-

cv.sail is the main function to do cross-validation along with plot, predict, and coef methods for objects of class cv.sail. We run it in parallel:

-
set.seed(432) # to reproduce results (randomness due to CV folds)
-library(doMC)
-#> Loading required package: foreach
-#> Loading required package: iterators
-#> Loading required package: parallel
-registerDoMC(cores = 2) 
-cvfit <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis,
-                 nfolds = 5, parallel = TRUE)
+

cv.sail is the main function to do cross-validation along with plot, predict, and coef methods for objects of class cv.sail. We can also run it in parallel:

+

We plot the cross-validated error curve which has the mean-squared error on the y-axis and \(\log(\lambda)\) on the x-axis. It includes the cross-validation curve (red dotted line), and upper and lower standard deviation curves along the \(\lambda\) sequence (error bars). Two selected \(\lambda\)’s are indicated by the vertical dotted lines (see below). The numbers at the top of the plot represent the total number of non-zero variables at that value of \(\lambda\) (df_main + df_environment + df_interaction):

-
plot(cvfit)
+
plot(cvfit)

lambda.min is the value of \(\lambda\) that gives minimum mean cross-validated error. The other \(\lambda\) saved is lambda.1se, which gives the most regularized model such that error is within one standard error of the minimum. We can view the selected \(\lambda\)’s and the corresponding coefficients:

-
cvfit[["lambda.min"]]
-#> [1] 0.2788543
-cvfit[["lambda.1se"]]
-#> [1] 0.4238337
+

The estimated coefficients at lambda.1se and lambda.min:

-
cbind(coef(cvfit, s="lambda.1se"), # lambda.1se is the default
-coef(cvfit, s = "lambda.min"))
-#> 202 x 2 sparse Matrix of class "dgCMatrix"
-#>                        1            1
-#> (Intercept)   5.42162243   5.43619701
-#> X1_1         -0.78253656  -1.23830516
-#> X1_2          0.13429262   0.48732240
-#> X1_3          0.43865579   0.88911732
-#> X1_4          0.79446840   1.10810480
-#> X1_5          1.92178800   2.68114985
-#> X2_1          .           -0.21979939
-#> X2_2          .           -0.95046682
-#> X2_3          .           -0.76046594
-#> X2_4          .           -0.17408785
-#> X2_5          .           -0.06842359
-#> X3_1          3.45105131   4.42740541
-#> X3_2          1.56761411   2.28691047
-#> X3_3         -1.27174989  -1.36817236
-#> X3_4         -2.27784639  -2.56642476
-#> X3_5         -1.23352658  -1.03097615
-#> X4_1          4.47171678   5.37947206
-#> X4_2         -2.87477819  -3.35562770
-#> X4_3         -6.65050142  -8.07333662
-#> X4_4         -3.44081136  -3.50308509
-#> X4_5         -0.47029997  -0.55029116
-#> X5_1          .            .         
-#> X5_2          .            .         
-#> X5_3          .            .         
-#> X5_4          .            .         
-#> X5_5          .            .         
-#> X6_1          .            .         
-#> X6_2          .            .         
-#> X6_3          .            .         
-#> X6_4          .            .         
-#> X6_5          .            .         
-#> X7_1          .            .         
-#> X7_2          .            .         
-#> X7_3          .            .         
-#> X7_4          .            .         
-#> X7_5          .            .         
-#> X8_1          0.17501411   0.47920984
-#> X8_2          0.11615654   0.33988638
-#> X8_3          0.01782976   0.07650873
-#> X8_4         -0.10502457  -0.28112125
-#> X8_5         -0.24477578  -0.66610209
-#> X9_1          .            .         
-#> X9_2          .            .         
-#> X9_3          .            .         
-#> X9_4          .            .         
-#> X9_5          .            .         
-#> X10_1         .            .         
-#> X10_2         .            .         
-#> X10_3         .            .         
-#> X10_4         .            .         
-#> X10_5         .            .         
-#> X11_1         0.13685648   0.34767475
-#> X11_2         0.02857112   0.06273705
-#> X11_3        -0.07321859  -0.20148715
-#> X11_4        -0.20935470  -0.67854244
-#> X11_5        -0.22638940  -0.69583368
-#> X12_1         .            .         
-#> X12_2         .            .         
-#> X12_3         .            .         
-#> X12_4         .            .         
-#> X12_5         .            .         
-#> X13_1         .            .         
-#> X13_2         .            .         
-#> X13_3         .            .         
-#> X13_4         .            .         
-#> X13_5         .            .         
-#> X14_1         .            .         
-#> X14_2         .            .         
-#> X14_3         .            .         
-#> X14_4         .            .         
-#> X14_5         .            .         
-#> X15_1         .            .         
-#> X15_2         .            .         
-#> X15_3         .            .         
-#> X15_4         .            .         
-#> X15_5         .            .         
-#> X16_1         .            .         
-#> X16_2         .            .         
-#> X16_3         .            .         
-#> X16_4         .            .         
-#> X16_5         .            .         
-#> X17_1         .            .         
-#> X17_2         .            .         
-#> X17_3         .            .         
-#> X17_4         .            .         
-#> X17_5         .            .         
-#> X18_1         .            .         
-#> X18_2         .            .         
-#> X18_3         .            .         
-#> X18_4         .            .         
-#> X18_5         .            .         
-#> X19_1         .            .         
-#> X19_2         .            .         
-#> X19_3         .            .         
-#> X19_4         .            .         
-#> X19_5         .            .         
-#> X20_1         .            0.10215979
-#> X20_2         .           -0.03829014
-#> X20_3         .           -0.17766509
-#> X20_4         .           -0.18547953
-#> X20_5         .            0.09733455
-#> E             1.99574559   2.06409655
-#> X1_1:E        .           -0.53455653
-#> X1_2:E        .            0.21036928
-#> X1_3:E        .            0.38381772
-#> X1_4:E        .            0.47835111
-#> X1_5:E        .            1.15740950
-#> X2_1:E        .            .         
-#> X2_2:E        .            .         
-#> X2_3:E        .            .         
-#> X2_4:E        .            .         
-#> X2_5:E        .            .         
-#> X3_1:E        1.80698510   2.37991172
-#> X3_2:E        0.82080940   1.22930803
-#> X3_3:E       -0.66589363  -0.73544867
-#> X3_4:E       -1.19269003  -1.37955841
-#> X3_5:E       -0.64587975  -0.55419190
-#> X4_1:E        8.31246506   8.87335933
-#> X4_2:E       -5.34391922  -5.53505808
-#> X4_3:E      -12.36260331 -13.31684893
-#> X4_4:E       -6.39611711  -5.77828687
-#> X4_5:E       -0.87423964  -0.90769710
-#> X5_1:E        .            .         
-#> X5_2:E        .            .         
-#> X5_3:E        .            .         
-#> X5_4:E        .            .         
-#> X5_5:E        .            .         
-#> X6_1:E        .            .         
-#> X6_2:E        .            .         
-#> X6_3:E        .            .         
-#> X6_4:E        .            .         
-#> X6_5:E        .            .         
-#> X7_1:E        .            .         
-#> X7_2:E        .            .         
-#> X7_3:E        .            .         
-#> X7_4:E        .            .         
-#> X7_5:E        .            .         
-#> X8_1:E        .            .         
-#> X8_2:E        .            .         
-#> X8_3:E        .            .         
-#> X8_4:E        .            .         
-#> X8_5:E        .            .         
-#> X9_1:E        .            .         
-#> X9_2:E        .            .         
-#> X9_3:E        .            .         
-#> X9_4:E        .            .         
-#> X9_5:E        .            .         
-#> X10_1:E       .            .         
-#> X10_2:E       .            .         
-#> X10_3:E       .            .         
-#> X10_4:E       .            .         
-#> X10_5:E       .            .         
-#> X11_1:E       .            .         
-#> X11_2:E       .            .         
-#> X11_3:E       .            .         
-#> X11_4:E       .            .         
-#> X11_5:E       .            .         
-#> X12_1:E       .            .         
-#> X12_2:E       .            .         
-#> X12_3:E       .            .         
-#> X12_4:E       .            .         
-#> X12_5:E       .            .         
-#> X13_1:E       .            .         
-#> X13_2:E       .            .         
-#> X13_3:E       .            .         
-#> X13_4:E       .            .         
-#> X13_5:E       .            .         
-#> X14_1:E       .            .         
-#> X14_2:E       .            .         
-#> X14_3:E       .            .         
-#> X14_4:E       .            .         
-#> X14_5:E       .            .         
-#> X15_1:E       .            .         
-#> X15_2:E       .            .         
-#> X15_3:E       .            .         
-#> X15_4:E       .            .         
-#> X15_5:E       .            .         
-#> X16_1:E       .            .         
-#> X16_2:E       .            .         
-#> X16_3:E       .            .         
-#> X16_4:E       .            .         
-#> X16_5:E       .            .         
-#> X17_1:E       .            .         
-#> X17_2:E       .            .         
-#> X17_3:E       .            .         
-#> X17_4:E       .            .         
-#> X17_5:E       .            .         
-#> X18_1:E       .            .         
-#> X18_2:E       .            .         
-#> X18_3:E       .            .         
-#> X18_4:E       .            .         
-#> X18_5:E       .            .         
-#> X19_1:E       .            .         
-#> X19_2:E       .            .         
-#> X19_3:E       .            .         
-#> X19_4:E       .            .         
-#> X19_5:E       .            .         
-#> X20_1:E       .            .         
-#> X20_2:E       .            .         
-#> X20_3:E       .            .         
-#> X20_4:E       .            .         
-#> X20_5:E       .            .
+
cbind(coef(cvfit, s="lambda.1se"), # lambda.1se is the default
+coef(cvfit, s = "lambda.min"))
+#> 122 x 2 sparse Matrix of class "dgCMatrix"
+#>                        1           1
+#> (Intercept)   5.44728244   5.4489968
+#> X1_1         -0.33479902  -0.3475998
+#> X1_2          0.46732277   0.6911858
+#> X1_3          1.70401603   2.1622040
+#> X2_1          .            .        
+#> X2_2          .            .        
+#> X2_3          .            .        
+#> X3_1          2.12553380   2.7746062
+#> X3_2         -1.81057790  -2.3950334
+#> X3_3         -2.10280952  -2.3355539
+#> X4_1         -0.26919665  -0.2769379
+#> X4_2         -7.58248628  -8.4137355
+#> X4_3         -1.62272272  -1.6547066
+#> X5_1          .            .        
+#> X5_2          .            .        
+#> X5_3          .            .        
+#> X6_1          .            .        
+#> X6_2          .            .        
+#> X6_3          .            .        
+#> X7_1          .            .        
+#> X7_2          .            .        
+#> X7_3          .            .        
+#> X8_1          0.07611936   0.2212063
+#> X8_2         -0.01517658  -0.0426662
+#> X8_3         -0.12663659  -0.3606695
+#> X9_1          .            .        
+#> X9_2          .            .        
+#> X9_3          .            .        
+#> X10_1         .            .        
+#> X10_2         .            .        
+#> X10_3         .            .        
+#> X11_1         0.06458267   0.1329899
+#> X11_2        -0.13771228  -0.3428515
+#> X11_3        -0.26279204  -0.6303841
+#> X12_1         .            .        
+#> X12_2         .            .        
+#> X12_3         .            .        
+#> X13_1         .            .        
+#> X13_2         .            .        
+#> X13_3         .            .        
+#> X14_1         .            .        
+#> X14_2         .            .        
+#> X14_3         .            .        
+#> X15_1         .            .        
+#> X15_2         .            .        
+#> X15_3         .            .        
+#> X16_1         .            .        
+#> X16_2         .            .        
+#> X16_3         .            .        
+#> X17_1         .            .        
+#> X17_2         .            .        
+#> X17_3         .            .        
+#> X18_1         .            .        
+#> X18_2         .            .        
+#> X18_3         .            .        
+#> X19_1         .            .        
+#> X19_2         .            .        
+#> X19_3         .            .        
+#> X20_1         .            .        
+#> X20_2         .            .        
+#> X20_3         .            .        
+#> E             1.94035362   1.9703742
+#> X1_1:E        .            .        
+#> X1_2:E        .            .        
+#> X1_3:E        .            .        
+#> X2_1:E        .            .        
+#> X2_2:E        .            .        
+#> X2_3:E        .            .        
+#> X3_1:E        0.89039027   1.4891105
+#> X3_2:E       -0.75845463  -1.2853966
+#> X3_3:E       -0.88087103  -1.2534744
+#> X4_1:E       -0.61790227  -0.5802235
+#> X4_2:E      -17.40450905 -17.6279480
+#> X4_3:E       -3.72472712  -3.4668409
+#> X5_1:E        .            .        
+#> X5_2:E        .            .        
+#> X5_3:E        .            .        
+#> X6_1:E        .            .        
+#> X6_2:E        .            .        
+#> X6_3:E        .            .        
+#> X7_1:E        .            .        
+#> X7_2:E        .            .        
+#> X7_3:E        .            .        
+#> X8_1:E        .            .        
+#> X8_2:E        .            .        
+#> X8_3:E        .            .        
+#> X9_1:E        .            .        
+#> X9_2:E        .            .        
+#> X9_3:E        .            .        
+#> X10_1:E       .            .        
+#> X10_2:E       .            .        
+#> X10_3:E       .            .        
+#> X11_1:E       .            .        
+#> X11_2:E       .            .        
+#> X11_3:E       .            .        
+#> X12_1:E       .            .        
+#> X12_2:E       .            .        
+#> X12_3:E       .            .        
+#> X13_1:E       .            .        
+#> X13_2:E       .            .        
+#> X13_3:E       .            .        
+#> X14_1:E       .            .        
+#> X14_2:E       .            .        
+#> X14_3:E       .            .        
+#> X15_1:E       .            .        
+#> X15_2:E       .            .        
+#> X15_3:E       .            .        
+#> X16_1:E       .            .        
+#> X16_2:E       .            .        
+#> X16_3:E       .            .        
+#> X17_1:E       .            .        
+#> X17_2:E       .            .        
+#> X17_3:E       .            .        
+#> X18_1:E       .            .        
+#> X18_2:E       .            .        
+#> X18_3:E       .            .        
+#> X19_1:E       .            .        
+#> X19_2:E       .            .        
+#> X19_3:E       .            .        
+#> X20_1:E       .            .        
+#> X20_2:E       .            .        
+#> X20_3:E       .            .

Estimated non-zero coefficients at lambda.1se:

-
predict(cvfit, type = "nonzero")
-#>                        1
-#> (Intercept)   5.42162243
-#> X1_1         -0.78253656
-#> X1_2          0.13429262
-#> X1_3          0.43865579
-#> X1_4          0.79446840
-#> X1_5          1.92178800
-#> X3_1          3.45105131
-#> X3_2          1.56761411
-#> X3_3         -1.27174989
-#> X3_4         -2.27784639
-#> X3_5         -1.23352658
-#> X4_1          4.47171678
-#> X4_2         -2.87477819
-#> X4_3         -6.65050142
-#> X4_4         -3.44081136
-#> X4_5         -0.47029997
-#> X8_1          0.17501411
-#> X8_2          0.11615654
-#> X8_3          0.01782976
-#> X8_4         -0.10502457
-#> X8_5         -0.24477578
-#> X11_1         0.13685648
-#> X11_2         0.02857112
-#> X11_3        -0.07321859
-#> X11_4        -0.20935470
-#> X11_5        -0.22638940
-#> E             1.99574559
-#> X3_1:E        1.80698510
-#> X3_2:E        0.82080940
-#> X3_3:E       -0.66589363
-#> X3_4:E       -1.19269003
-#> X3_5:E       -0.64587975
-#> X4_1:E        8.31246506
-#> X4_2:E       -5.34391922
-#> X4_3:E      -12.36260331
-#> X4_4:E       -6.39611711
-#> X4_5:E       -0.87423964
+

@@ -1236,19 +1158,19 @@

Main Effects

Since we are using simulated data, we also plot the true curve:

-
plotMain(cvfit$sail.fit, x = sailsim$x, xvar = "X3",
-         legend.position = "topright",
-         s = cvfit$lambda.min, f.truth = sailsim$f3)
+

Interaction Effects

Again, since we are using simulated data, we also plot the true interaction:

-
plotInter(cvfit$sail.fit, x = sailsim$x, xvar = "X4",
-          f.truth = sailsim$f4.inter,
-          s = cvfit$lambda.min,
-          title_z = "Estimated")
+

@@ -1256,67 +1178,69 @@

Linear Interactions

The basis argument in the sail function is very flexible in that it allows you to apply any basis expansion to the columns of \(\mathbf{X}\). Of course, there might be situations where you do not expect any non-linear main effects or interactions to be present in your data. You can still use the sail method to search for linear main effects and interactions. This can be accomplished by specifying an identity map:

-
f.identity <- function(i) i
+

We then pass this function to basis argument in cv.sail:

-
cvfit_linear <- cv.sail(x = sailsim$x, y = sailsim$y, e = sailsim$e,
-                        basis = f.identity, nfolds = 5, parallel = TRUE)
+

Next we plot the cross-validated curve:

-
plot(cvfit_linear)
+
plot(cvfit_linear)

And extract the model at lambda.min:

-
coef(cvfit_linear, s = "lambda.min")
-#> 42 x 1 sparse Matrix of class "dgCMatrix"
-#>                       1
-#> (Intercept)   5.4385233
-#> X1_1          2.4568905
-#> X2_1         -1.6516411
-#> X3_1         -5.1515618
-#> X4_1         -7.1355682
-#> X5_1          .        
-#> X6_1          .        
-#> X7_1         -1.1055226
-#> X8_1         -0.8602264
-#> X9_1          .        
-#> X10_1         .        
-#> X11_1        -2.1990113
-#> X12_1         .        
-#> X13_1         .        
-#> X14_1        -1.9208173
-#> X15_1         .        
-#> X16_1         3.2004658
-#> X17_1         .        
-#> X18_1         1.0234816
-#> X19_1         .        
-#> X20_1        -0.2161608
-#> E             2.4466054
-#> X1_1:E       -4.3993869
-#> X2_1:E       -2.7114248
-#> X3_1:E       -4.7196594
-#> X4_1:E      -12.9774650
-#> X5_1:E        .        
-#> X6_1:E        .        
-#> X7_1:E        2.3703946
-#> X8_1:E        .        
-#> X9_1:E        .        
-#> X10_1:E       .        
-#> X11_1:E      -2.1462173
-#> X12_1:E       .        
-#> X13_1:E       .        
-#> X14_1:E      -0.9787678
-#> X15_1:E       .        
-#> X16_1:E       6.9265731
-#> X17_1:E       .        
-#> X18_1:E       1.9004167
-#> X19_1:E       .        
-#> X20_1:E       .
+

Applying a different penalty to each predictor

Recall that we consider the following penalized least squares criterion for this problem:

-\[\begin{equation} +

\[\begin{equation} \arg\min_{\boldsymbol{\theta} } \mathcal{L}(Y;\boldsymbol{\theta}) + \lambda (1-\alpha) \left( w_E |\beta_E| + \sum_{j=1}^{p} w_j \lVert\boldsymbol{\theta}_j \rVert_2 \right) + \lambda\alpha \sum_{j=1}^{p} w_{jE} |\gamma_{j}| -\end{equation}\] +\end{equation}\]

The weights \(w_E, w_j, w_{jE}\) are by default set to 1 as specified by the penalty.factor argument. This argument allows users to apply separate penalty factors to each coefficient. In particular, any variable with penalty.factor equal to zero is not penalized at all. This feature can be applied mainly for two reasons:

  1. Prior knowledge about the importance of certain variables is known. Larger weights will penalize the variable more, while smaller weights will penalize the variable less
    @@ -1325,17 +1249,20 @@

In the following example, we want the environment variable to always be included so we set the first element of p.fac to zero. We also want to apply less of a penalty to the main effects for \(X_2, X_3, X_4\):

-
# the weights correspond to E, X1, X2, X3, ... X_p, X1:E, X2:E, ... X_p:E
-p.fac <- c(0, 1, 0.4, 0.6, 0.7, rep(1, 2*ncol(sailsim$x) - 4))
-
fit_pf <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis,
-               penalty.factor = p.fac)
-
plot(fit_pf)
+ +
fit_pf <- sail(x = sailsim$x, y = sailsim$y, e = sailsim$e, basis = f.basis,
+               nlambda = 50,
+               dfmax = 10, # to speed up vignette build time
+               penalty.factor = p.fac)
+
plot(fit_pf)

We see from the plot above that the black line (corresponding to the \(E\) variable with penalty.factor equal to zero) is always included in the model.

- diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-13-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-13-1.png index 0d736cc..a55479d 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-13-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-13-1.png differ diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-17-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-17-1.png index 0018292..d472d13 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-17-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-17-1.png differ diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-18-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-18-1.png index 5b6fba3..997609b 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-18-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-18-1.png differ diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-21-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-21-1.png index b24396f..254b8bc 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-21-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-21-1.png differ diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-25-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-25-1.png index 7eadce1..d6551c3 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-25-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-25-1.png differ diff --git a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-6-1.png b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-6-1.png index c947e43..281d536 100644 Binary files a/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-6-1.png and b/docs/articles/introduction-to-sail_files/figure-html/unnamed-chunk-6-1.png differ diff --git a/docs/articles/user-defined-design.html b/docs/articles/user-defined-design.html index 42062f4..dde5808 100644 --- a/docs/articles/user-defined-design.html +++ b/docs/articles/user-defined-design.html @@ -1,35 +1,39 @@ - + Supplying a User Defined Design Matrix • sail - - - - + + + + + + + - +
-

A limitation of the sail method is that the same basis expansion function \(f(\cdot)\) is applied to all columns of the predictor matrix \(\mathbf{X}\). Being able to automatically select linear vs. nonlinear components was not a focus of our paper, but is an active area of reserch for main effects only e.g. ref1 and ref2.

+

A limitation of the sail method is that the same basis expansion function \(f(\cdot)\) is applied to all columns of the predictor matrix \(\mathbf{X}\). Being able to automatically select linear vs. nonlinear components was not a focus of our paper, but is an active area of research for main effects only e.g. ref1 and ref2.

However, if the user has some prior knowledge on possible effect relationships, then they can supply their own design matrix. This can be useful for example, when one has a combination of categorical (e.g. gender, race) and continuous variables, but would only like to apply \(f(\cdot)\) on the continuous variables. We provide an example below to illustrate this functionality.

User-defined design matrix

We use the simulated dataset sailsim provided in our package. We first add a categorical variable race to the data:

-
set.seed(1234)
-library(sail)
-x_df <- as.data.frame(sailsim$x)
-x_df$race <- factor(sample(1:5, nrow(x_df), replace = TRUE))
-table(x_df$race)
-#> 
-#>  1  2  3  4  5 
-#> 25 26 17 17 15
+
set.seed(1234)
+library(sail)
+x_df <- as.data.frame(sailsim$x)
+x_df$race <- factor(sample(1:5, nrow(x_df), replace = TRUE))
+table(x_df$race)
+#> 
+#>  1  2  3  4  5 
+#> 19 19 21 22 19

We then use the model.matrix function to create the design matrix. Note that the intercept should not be included, as this is added internally in the sail function. This is why we add 0 to the formula. Notice also the flexibility we can have by including different basis expansions to each predictor:

-
library(splines)
-x <- stats::model.matrix(~ 0 +  bs(X1, degree = 5) + bs(X2, degree = 3) + ns(X3, df = 8) + 
-                           bs(X4, degree = 6) + X5 + poly(X6,2) + race, data = x_df)
-head(x)
-#>   bs(X1, degree = 5)1 bs(X1, degree = 5)2 bs(X1, degree = 5)3
-#> 1        0.0001654794         0.003945507        0.0470361237
-#> 2        0.2470181057         0.345144379        0.2411253263
-#> 3        0.1299195522         0.007832449        0.0002360971
-#> 4        0.3808392973         0.121815907        0.0194821217
-#> 5        0.1737663057         0.014898419        0.0006386822
-#> 6        0.1184145931         0.281407715        0.3343772913
-#>   bs(X1, degree = 5)4 bs(X1, degree = 5)5 bs(X2, degree = 3)1
-#> 1        2.803692e-01        6.684809e-01           0.3272340
-#> 2        8.422768e-02        1.176866e-02           0.3065738
-#> 3        3.558391e-06        2.145244e-08           0.1896790
-#> 4        1.557896e-03        4.983113e-05           0.4100900
-#> 5        1.368987e-05        1.173746e-07           0.3946500
-#> 6        1.986587e-01        4.721047e-02           0.3175164
-#>   bs(X2, degree = 3)2 bs(X2, degree = 3)3 ns(X3, df = 8)1 ns(X3, df = 8)2
-#> 1          0.41274967         0.173537682      0.06566652               0
-#> 2          0.04879618         0.002588901      0.00000000               0
-#> 3          0.01508834         0.000400076      0.00000000               0
-#> 4          0.12345871         0.012389196      0.00000000               0
-#> 5          0.35302552         0.105263760      0.00000000               0
-#> 6          0.05370432         0.003027827      0.00000000               0
-#>   ns(X3, df = 8)3 ns(X3, df = 8)4 ns(X3, df = 8)5 ns(X3, df = 8)6
-#> 1     0.000000000    0.000000e+00       0.0000000   -1.589937e-01
-#> 2     0.000000000    5.775107e-04       0.3179489    5.395130e-01
-#> 3     0.000000000    4.989926e-03       0.4147696    4.830810e-01
-#> 4     0.133404268    6.839146e-01       0.1826811    3.022366e-08
-#> 5     0.000000000    8.944913e-05       0.2775548    5.564842e-01
-#> 6     0.001578195    3.415384e-01       0.6070588    4.566909e-02
-#>   ns(X3, df = 8)7 ns(X3, df = 8)8 bs(X4, degree = 6)1 bs(X4, degree = 6)2
-#> 1    4.436233e-01   -2.846296e-01        0.1820918880        0.3088147022
-#> 2    1.732713e-01   -3.131078e-02        0.0120101010        0.0000608354
-#> 3    1.434410e-01   -4.628144e-02        0.0002900763        0.0044075535
-#> 4    7.673343e-09   -4.923233e-09        0.2978877432        0.0579746877
-#> 5    1.863219e-01   -2.045032e-02        0.0114895681        0.0645689076
-#> 6    1.159471e-02   -7.439189e-03        0.0102152807        0.0595722132
-#>   bs(X4, degree = 6)3 bs(X4, degree = 6)4 bs(X4, degree = 6)5
-#> 1        2.793213e-01        1.421126e-01        3.856204e-02
-#> 2        1.643482e-07        2.497444e-10        2.024070e-13
-#> 3        3.571755e-02        1.628127e-01        3.958163e-01
-#> 4        6.017595e-03        3.513419e-04        1.094046e-05
-#> 5        1.935272e-01        3.262743e-01        2.933747e-01
-#> 6        1.852831e-01        3.241534e-01        3.024572e-01
-#>   bs(X4, degree = 6)6         X5 poly(X6, 2)1 poly(X6, 2)2 race1 race2
-#> 1        4.359896e-03 0.51332996  -0.13705545   0.09851639     1     0
-#> 2        6.835086e-17 0.02643863   0.18835303   0.22584415     0     0
-#> 3        4.009478e-01 0.76746637  -0.15841216   0.16140597     0     0
-#> 4        1.419483e-07 0.69077618  -0.03664279  -0.07954100     0     0
-#> 5        1.099135e-01 0.27718210   0.13128945   0.05620199     0     0
-#> 6        1.175889e-01 0.48384748   0.08486354  -0.03559388     0     0
-#>   race3 race4 race5
-#> 1     0     0     0
-#> 2     0     1     0
-#> 3     0     1     0
-#> 4     0     1     0
-#> 5     0     0     1
-#> 6     0     1     0
-

One benefit of using stats::model.matrix is that it returns the group membership as an attribute:

-
attr(x, "assign")
-#>  [1] 1 1 1 1 1 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 5 6 6 7 7 7 7 7
+
library(splines)
+x <- stats::model.matrix(~ 0 +  bs(X1, degree = 5) + bs(X2, degree = 3) + ns(X3, df = 8) + 
+                           bs(X4, degree = 6) + X5 + poly(X6,2) + race, data = x_df)
+head(x)
+#>   bs(X1, degree = 5)1 bs(X1, degree = 5)2 bs(X1, degree = 5)3
+#> 1        0.0001654794         0.003945507        0.0470361237
+#> 2        0.2470181057         0.345144379        0.2411253263
+#> 3        0.1299195522         0.007832449        0.0002360971
+#> 4        0.3808392973         0.121815907        0.0194821217
+#> 5        0.1737663057         0.014898419        0.0006386822
+#> 6        0.1184145931         0.281407715        0.3343772913
+#>   bs(X1, degree = 5)4 bs(X1, degree = 5)5 bs(X2, degree = 3)1
+#> 1        2.803692e-01        6.684809e-01           0.3272340
+#> 2        8.422768e-02        1.176866e-02           0.3065738
+#> 3        3.558391e-06        2.145244e-08           0.1896790
+#> 4        1.557896e-03        4.983113e-05           0.4100900
+#> 5        1.368987e-05        1.173746e-07           0.3946500
+#> 6        1.986587e-01        4.721047e-02           0.3175164
+#>   bs(X2, degree = 3)2 bs(X2, degree = 3)3 ns(X3, df = 8)1 ns(X3, df = 8)2
+#> 1          0.41274967         0.173537682      0.06566652               0
+#> 2          0.04879618         0.002588901      0.00000000               0
+#> 3          0.01508834         0.000400076      0.00000000               0
+#> 4          0.12345871         0.012389196      0.00000000               0
+#> 5          0.35302552         0.105263760      0.00000000               0
+#> 6          0.05370432         0.003027827      0.00000000               0
+#>   ns(X3, df = 8)3 ns(X3, df = 8)4 ns(X3, df = 8)5 ns(X3, df = 8)6
+#> 1     0.000000000    0.000000e+00       0.0000000   -1.589937e-01
+#> 2     0.000000000    5.775107e-04       0.3179489    5.395130e-01
+#> 3     0.000000000    4.989926e-03       0.4147696    4.830810e-01
+#> 4     0.133404268    6.839146e-01       0.1826811    3.022366e-08
+#> 5     0.000000000    8.944913e-05       0.2775548    5.564842e-01
+#> 6     0.001578195    3.415384e-01       0.6070588    4.566909e-02
+#>   ns(X3, df = 8)7 ns(X3, df = 8)8 bs(X4, degree = 6)1 bs(X4, degree = 6)2
+#> 1    4.436233e-01   -2.846296e-01        0.1820918880        0.3088147022
+#> 2    1.732713e-01   -3.131078e-02        0.0120101010        0.0000608354
+#> 3    1.434410e-01   -4.628144e-02        0.0002900763        0.0044075535
+#> 4    7.673343e-09   -4.923233e-09        0.2978877432        0.0579746877
+#> 5    1.863219e-01   -2.045032e-02        0.0114895681        0.0645689076
+#> 6    1.159471e-02   -7.439189e-03        0.0102152807        0.0595722132
+#>   bs(X4, degree = 6)3 bs(X4, degree = 6)4 bs(X4, degree = 6)5
+#> 1        2.793213e-01        1.421126e-01        3.856204e-02
+#> 2        1.643482e-07        2.497444e-10        2.024070e-13
+#> 3        3.571755e-02        1.628127e-01        3.958163e-01
+#> 4        6.017595e-03        3.513419e-04        1.094046e-05
+#> 5        1.935272e-01        3.262743e-01        2.933747e-01
+#> 6        1.852831e-01        3.241534e-01        3.024572e-01
+#>   bs(X4, degree = 6)6         X5 poly(X6, 2)1 poly(X6, 2)2 race1 race2
+#> 1        4.359896e-03 0.51332996  -0.13705545   0.09851639     0     0
+#> 2        6.835086e-17 0.02643863   0.18835303   0.22584415     0     1
+#> 3        4.009478e-01 0.76746637  -0.15841216   0.16140597     0     0
+#> 4        1.419483e-07 0.69077618  -0.03664279  -0.07954100     0     0
+#> 5        1.099135e-01 0.27718210   0.13128945   0.05620199     1     0
+#> 6        1.175889e-01 0.48384748   0.08486354  -0.03559388     0     0
+#>   race3 race4 race5
+#> 1     0     1     0
+#> 2     0     0     0
+#> 3     0     0     1
+#> 4     0     1     0
+#> 5     0     0     0
+#> 6     0     0     1
+

One benefit of using stats::model.matrix is that it returns the group membership as an attribute:

+

The group membership must be supplied to the sail function. This information is needed for the group lasso penalty, which will select the whole group as zero or non-zero.

Fit the sail model

We need to set the argument expand = FALSE and provide the group membership. The first element of the group membership corresponds to the first column of x, the second element to the second column of x, and so on.

-
fit_design <- sail(x = x, y = sailsim$y, e = sailsim$e, 
-                   expand = FALSE,
-                   group = attr(x, "assign"), verbose = 0)
+
fit_design <- sail(x = x, y = sailsim$y, e = sailsim$e, 
+                   expand = FALSE,
+                   group = attr(x, "assign"), verbose = 0)

We can plot the solution path for both main effects and interactions using the plot method for objects of class sail:

-
plot(fit_design)
+
plot(fit_design)

In this instance, since we provided a user-defined design matrix and expand = FALSE, the numbers at the top of the plot represent the total number of non-zero coefficients.

@@ -193,132 +191,134 @@

Find the optimal value for lambda

We can use cross-validation to find the optimal value of lambda:

-
library(doMC)
-#> Loading required package: foreach
-#> Loading required package: iterators
-#> Loading required package: parallel
-registerDoMC(cores = 2)
-cvfit_design <- cv.sail(x = x, y = sailsim$y, e = sailsim$e, 
-                        expand = FALSE,
-                        group = attr(x, "assign"), verbose = 0,
-                        nfolds = 10, parallel = TRUE)
+

We can plot the cross-validated mean squared error as a function of lambda:

-
plot(cvfit_design)
+
plot(cvfit_design)

The estimated coefficients at lambda.1se and lambda.min are:

-
cbind(coef(cvfit_design, s="lambda.1se"), # lambda.1se is the default
-coef(cvfit_design, s = "lambda.min"))
-#> 62 x 2 sparse Matrix of class "dgCMatrix"
-#>                                 1            1
-#> (Intercept)            5.42057935   5.45022411
-#> bs(X1, degree = 5)1   -0.38913702  -0.99980981
-#> bs(X1, degree = 5)2    0.00947607   0.84044532
-#> bs(X1, degree = 5)3    0.17875174   1.11415914
-#> bs(X1, degree = 5)4    0.40379077   1.16368947
-#> bs(X1, degree = 5)5    0.98556730   2.63944592
-#> bs(X2, degree = 3)1    .           -1.17689836
-#> bs(X2, degree = 3)2    .           -1.03093803
-#> bs(X2, degree = 3)3    .           -0.23466071
-#> ns(X3, df = 8)1        2.17658372   3.43257956
-#> ns(X3, df = 8)2        1.94334296   2.64241254
-#> ns(X3, df = 8)3        0.65644441   1.07346393
-#> ns(X3, df = 8)4       -1.16599084  -0.86948704
-#> ns(X3, df = 8)5       -1.62789320  -1.61625869
-#> ns(X3, df = 8)6       -1.29567515  -1.36272297
-#> ns(X3, df = 8)7        0.46196993   0.51920037
-#> ns(X3, df = 8)8       -1.12199469  -1.58839548
-#> bs(X4, degree = 6)1    4.25730420   5.97839856
-#> bs(X4, degree = 6)2   -0.21970890   0.09042593
-#> bs(X4, degree = 6)3   -4.38745682  -7.10265598
-#> bs(X4, degree = 6)4   -4.56639589  -6.62018513
-#> bs(X4, degree = 6)5   -2.00248806  -1.84209587
-#> bs(X4, degree = 6)6   -0.17598921  -0.35682238
-#> X5                     .            .         
-#> poly(X6, 2)1           .            .         
-#> poly(X6, 2)2           .            .         
-#> race1                  0.22601077   0.37075174
-#> race2                 -0.13058802  -0.20968551
-#> race3                  0.18074321   0.31408729
-#> race4                 -0.09159055  -0.13947230
-#> race5                 -0.18457540  -0.33568122
-#> E                      1.93814553   2.12863361
-#> bs(X1, degree = 5)1:E  .           -0.44742651
-#> bs(X1, degree = 5)2:E  .            0.37610905
-#> bs(X1, degree = 5)3:E  .            0.49859916
-#> bs(X1, degree = 5)4:E  .            0.52076456
-#> bs(X1, degree = 5)5:E  .            1.18118272
-#> bs(X2, degree = 3)1:E  .            .         
-#> bs(X2, degree = 3)2:E  .            .         
-#> bs(X2, degree = 3)3:E  .            .         
-#> ns(X3, df = 8)1:E      0.95642364   1.97522674
-#> ns(X3, df = 8)2:E      0.85393413   1.52053690
-#> ns(X3, df = 8)3:E      0.28845155   0.61770882
-#> ns(X3, df = 8)4:E     -0.51235392  -0.50033335
-#> ns(X3, df = 8)5:E     -0.71532077  -0.93005197
-#> ns(X3, df = 8)6:E     -0.56933916  -0.78415862
-#> ns(X3, df = 8)7:E      0.20299654   0.29876611
-#> ns(X3, df = 8)8:E     -0.49302135  -0.91401850
-#> bs(X4, degree = 6)1:E  8.46740068   9.02807791
-#> bs(X4, degree = 6)2:E -0.43698152   0.13655369
-#> bs(X4, degree = 6)3:E -8.72626271 -10.72583750
-#> bs(X4, degree = 6)4:E -9.08215666  -9.99725035
-#> bs(X4, degree = 6)5:E -3.98277126  -2.78177924
-#> bs(X4, degree = 6)6:E -0.35002695  -0.53884334
-#> X5:E                   .            .         
-#> poly(X6, 2)1:E         .            .         
-#> poly(X6, 2)2:E         .            .         
-#> race1:E                .            .         
-#> race2:E                .            .         
-#> race3:E                .            .         
-#> race4:E                .            .         
-#> race5:E                .            .
+
cbind(coef(cvfit_design, s="lambda.1se"), # lambda.1se is the default
+coef(cvfit_design, s = "lambda.min"))
+#> 62 x 2 sparse Matrix of class "dgCMatrix"
+#>                                1            1
+#> (Intercept)            5.4253975   5.40401047
+#> bs(X1, degree = 5)1   -0.6899301  -0.74778821
+#> bs(X1, degree = 5)2    0.1911426   1.68993883
+#> bs(X1, degree = 5)3    0.4510229   1.48165273
+#> bs(X1, degree = 5)4    0.7729722   1.56859507
+#> bs(X1, degree = 5)5    1.8254898   3.14653210
+#> bs(X2, degree = 3)1    .          -1.34551165
+#> bs(X2, degree = 3)2    .          -2.31592314
+#> bs(X2, degree = 3)3    .          -1.43110420
+#> ns(X3, df = 8)1        2.6276828   4.55045507
+#> ns(X3, df = 8)2        2.2646976   3.20379892
+#> ns(X3, df = 8)3        0.8060530   0.70088507
+#> ns(X3, df = 8)4       -1.1317318  -0.32899504
+#> ns(X3, df = 8)5       -1.5879515  -1.27410597
+#> ns(X3, df = 8)6       -1.4845064  -1.52735344
+#> ns(X3, df = 8)7        0.4838480   0.23243096
+#> ns(X3, df = 8)8       -1.3282831  -1.77795193
+#> bs(X4, degree = 6)1    4.9112108   7.06673607
+#> bs(X4, degree = 6)2   -0.2583294   1.67099688
+#> bs(X4, degree = 6)3   -5.3372680  -7.87279581
+#> bs(X4, degree = 6)4   -5.4476495  -7.94157576
+#> bs(X4, degree = 6)5   -2.2254989  -1.75153600
+#> bs(X4, degree = 6)6   -0.1776067  -0.30481902
+#> X5                     .           .         
+#> poly(X6, 2)1           .           .         
+#> poly(X6, 2)2           .           .         
+#> race1                 -0.0433420  -0.06193825
+#> race2                 -0.1622336   0.05028432
+#> race3                  0.2570618   0.29940124
+#> race4                 -0.4670934  -0.84307180
+#> race5                  0.4156071   0.55532449
+#> E                      1.9929608   2.34649146
+#> bs(X1, degree = 5)1:E  .          -0.18424671
+#> bs(X1, degree = 5)2:E  .           0.41638216
+#> bs(X1, degree = 5)3:E  .           0.36506278
+#> bs(X1, degree = 5)4:E  .           0.38648440
+#> bs(X1, degree = 5)5:E  .           0.77527056
+#> bs(X2, degree = 3)1:E  .          -3.92381433
+#> bs(X2, degree = 3)2:E  .          -6.75375232
+#> bs(X2, degree = 3)3:E  .          -4.17342145
+#> ns(X3, df = 8)1:E      1.3301226   3.25187237
+#> ns(X3, df = 8)2:E      1.1463810   2.28951721
+#> ns(X3, df = 8)3:E      0.4080208   0.50087052
+#> ns(X3, df = 8)4:E     -0.5728782  -0.23510833
+#> ns(X3, df = 8)5:E     -0.8038148  -0.91050893
+#> ns(X3, df = 8)6:E     -0.7514513  -1.09148610
+#> ns(X3, df = 8)7:E      0.2449219   0.16610115
+#> ns(X3, df = 8)8:E     -0.6723717  -1.27057024
+#> bs(X4, degree = 6)1:E  8.6599091   9.88383976
+#> bs(X4, degree = 6)2:E -0.4555107   2.33712781
+#> bs(X4, degree = 6)3:E -9.4111733 -11.01122944
+#> bs(X4, degree = 6)4:E -9.6058083 -11.10742802
+#> bs(X4, degree = 6)5:E -3.9242091  -2.44977328
+#> bs(X4, degree = 6)6:E -0.3131728  -0.42633293
+#> X5:E                   .           .         
+#> poly(X6, 2)1:E         .           .         
+#> poly(X6, 2)2:E         .           .         
+#> race1:E                .           .         
+#> race2:E                .           .         
+#> race3:E                .           .         
+#> race4:E                .           .         
+#> race5:E                .           .

The estimated non-zero coefficients at lambda.1se:

-
predict(cvfit_design, type = "nonzero")
-#>                                 1
-#> (Intercept)            5.42057935
-#> bs(X1, degree = 5)1   -0.38913702
-#> bs(X1, degree = 5)2    0.00947607
-#> bs(X1, degree = 5)3    0.17875174
-#> bs(X1, degree = 5)4    0.40379077
-#> bs(X1, degree = 5)5    0.98556730
-#> ns(X3, df = 8)1        2.17658372
-#> ns(X3, df = 8)2        1.94334296
-#> ns(X3, df = 8)3        0.65644441
-#> ns(X3, df = 8)4       -1.16599084
-#> ns(X3, df = 8)5       -1.62789320
-#> ns(X3, df = 8)6       -1.29567515
-#> ns(X3, df = 8)7        0.46196993
-#> ns(X3, df = 8)8       -1.12199469
-#> bs(X4, degree = 6)1    4.25730420
-#> bs(X4, degree = 6)2   -0.21970890
-#> bs(X4, degree = 6)3   -4.38745682
-#> bs(X4, degree = 6)4   -4.56639589
-#> bs(X4, degree = 6)5   -2.00248806
-#> bs(X4, degree = 6)6   -0.17598921
-#> race1                  0.22601077
-#> race2                 -0.13058802
-#> race3                  0.18074321
-#> race4                 -0.09159055
-#> race5                 -0.18457540
-#> E                      1.93814553
-#> ns(X3, df = 8)1:E      0.95642364
-#> ns(X3, df = 8)2:E      0.85393413
-#> ns(X3, df = 8)3:E      0.28845155
-#> ns(X3, df = 8)4:E     -0.51235392
-#> ns(X3, df = 8)5:E     -0.71532077
-#> ns(X3, df = 8)6:E     -0.56933916
-#> ns(X3, df = 8)7:E      0.20299654
-#> ns(X3, df = 8)8:E     -0.49302135
-#> bs(X4, degree = 6)1:E  8.46740068
-#> bs(X4, degree = 6)2:E -0.43698152
-#> bs(X4, degree = 6)3:E -8.72626271
-#> bs(X4, degree = 6)4:E -9.08215666
-#> bs(X4, degree = 6)5:E -3.98277126
-#> bs(X4, degree = 6)6:E -0.35002695
+
- diff --git a/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-5-1.png b/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-5-1.png index f866e7f..3e54997 100644 Binary files a/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-5-1.png and b/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-5-1.png differ diff --git a/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-7-1.png b/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-7-1.png index 5af0568..08acf26 100644 Binary files a/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-7-1.png and b/docs/articles/user-defined-design_files/figure-html/unnamed-chunk-7-1.png differ diff --git a/docs/authors.html b/docs/authors.html index 1375587..d203194 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -1,6 +1,6 @@ - + @@ -8,28 +8,47 @@ Authors • sail + - + - + + - + - + + - + + + + + - + + + + + + + + + + + + - + + - - @@ -50,14 +65,15 @@ - + + + diff --git a/docs/docsearch.css b/docs/docsearch.css new file mode 100644 index 0000000..e5f1fe1 --- /dev/null +++ b/docs/docsearch.css @@ -0,0 +1,148 @@ +/* Docsearch -------------------------------------------------------------- */ +/* + Source: https://github.com/algolia/docsearch/ + License: MIT +*/ + +.algolia-autocomplete { + display: block; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.algolia-autocomplete .ds-dropdown-menu { + width: 100%; + min-width: none; + max-width: none; + padding: .75rem 0; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .1); + box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); +} + +@media (min-width:768px) { + .algolia-autocomplete .ds-dropdown-menu { + width: 175% + } +} + +.algolia-autocomplete .ds-dropdown-menu::before { + display: none +} + +.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { + padding: 0; + background-color: rgb(255,255,255); + border: 0; + max-height: 80vh; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { + margin-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion { + padding: 0; + overflow: visible +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { + padding: .125rem 1rem; + margin-top: 0; + font-size: 1.3em; + font-weight: 500; + color: #00008B; + border-bottom: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { + float: none; + padding-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { + float: none; + width: auto; + padding: 0; + text-align: left +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content { + float: none; + width: auto; + padding: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content::before { + display: none +} + +.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { + padding-top: .75rem; + margin-top: .75rem; + border-top: 1px solid rgba(0, 0, 0, .1) +} + +.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { + display: block; + padding: .1rem 1rem; + margin-bottom: 0.1; + font-size: 1.0em; + font-weight: 400 + /* display: none */ +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { + display: block; + padding: .25rem 1rem; + margin-bottom: 0; + font-size: 0.9em; + font-weight: 400 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text { + padding: 0 1rem .5rem; + margin-top: -.25rem; + font-size: 0.8em; + font-weight: 400; + line-height: 1.25 +} + +.algolia-autocomplete .algolia-docsearch-footer { + width: 110px; + height: 20px; + z-index: 3; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} + +.algolia-autocomplete .algolia-docsearch-footer--logo { + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-position: 50%; + background-size: 100%; + overflow: hidden; + text-indent: -9000px; + width: 100%; + height: 100%; + display: block; + transform: translate(-8px); +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { + color: #FF8C00; + background: rgba(232, 189, 54, 0.1) +} + + +.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) +} + +.algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { + background-color: rgba(192, 192, 192, .15) +} diff --git a/docs/docsearch.js b/docs/docsearch.js new file mode 100644 index 0000000..b35504c --- /dev/null +++ b/docs/docsearch.js @@ -0,0 +1,85 @@ +$(function() { + + // register a handler to move the focus to the search bar + // upon pressing shift + "/" (i.e. "?") + $(document).on('keydown', function(e) { + if (e.shiftKey && e.keyCode == 191) { + e.preventDefault(); + $("#search-input").focus(); + } + }); + + $(document).ready(function() { + // do keyword highlighting + /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ + var mark = function() { + + var referrer = document.URL ; + var paramKey = "q" ; + + if (referrer.indexOf("?") !== -1) { + var qs = referrer.substr(referrer.indexOf('?') + 1); + var qs_noanchor = qs.split('#')[0]; + var qsa = qs_noanchor.split('&'); + var keyword = ""; + + for (var i = 0; i < qsa.length; i++) { + var currentParam = qsa[i].split('='); + + if (currentParam.length !== 2) { + continue; + } + + if (currentParam[0] == paramKey) { + keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); + } + } + + if (keyword !== "") { + $(".contents").unmark({ + done: function() { + $(".contents").mark(keyword); + } + }); + } + } + }; + + mark(); + }); +}); + +/* Search term highlighting ------------------------------*/ + +function matchedWords(hit) { + var words = []; + + var hierarchy = hit._highlightResult.hierarchy; + // loop to fetch from lvl0, lvl1, etc. + for (var idx in hierarchy) { + words = words.concat(hierarchy[idx].matchedWords); + } + + var content = hit._highlightResult.content; + if (content) { + words = words.concat(content.matchedWords); + } + + // return unique words + var words_uniq = [...new Set(words)]; + return words_uniq; +} + +function updateHitURL(hit) { + + var words = matchedWords(hit); + var url = ""; + + if (hit.anchor) { + url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; + } else { + url = hit.url + '?q=' + escape(words.join(" ")); + } + + return url; +} diff --git a/docs/docsearch.json b/docs/docsearch.json index 6d0585f..e2137e5 100644 --- a/docs/docsearch.json +++ b/docs/docsearch.json @@ -1,21 +1,95 @@ { "index_name": "sail", "start_urls": [ - "http://sahirbhatnagar.com/sail" + { + "url": "http://sahirbhatnagar.com/sail/index.html", + "selectors_key": "homepage", + "tags": [ + "homepage" + ] + }, + { + "url": "http://sahirbhatnagar.com/sail/reference", + "selectors_key": "reference", + "tags": [ + "reference" + ] + }, + { + "url": "http://sahirbhatnagar.com/sail/articles", + "selectors_key": "articles", + "tags": [ + "articles" + ] + } + ], + "stop_urls": [ + "/reference/$", + "/reference/index.html", + "/articles/$", + "/articles/index.html" ], - "stop_urls": ["index.html", "authors.html", "/LICENSE", "/news/"], "sitemap_urls": [ "http://sahirbhatnagar.com/sail/sitemap.xml" ], "selectors": { - "lvl0": ".contents h1", - "lvl1": ".contents .name", - "lvl2": ".contents h2", - "lvl3": ".contents h3, .contents th", - "lvl4": ".contents h4", - "text": ".contents p, .contents li, .usage, .template-article .contents .pre" + "homepage": { + "lvl0": { + "selector": ".contents h1", + "default_value": "sail Home page" + }, + "lvl1": { + "selector": ".contents h2" + }, + "lvl2": { + "selector": ".contents h3", + "default_value": "Context" + }, + "lvl3": ".ref-arguments td, .ref-description", + "text": ".contents p, .contents li, .contents .pre" + }, + "reference": { + "lvl0": { + "selector": ".contents h1" + }, + "lvl1": { + "selector": ".contents .name", + "default_value": "Argument" + }, + "lvl2": { + "selector": ".ref-arguments th", + "default_value": "Description" + }, + "lvl3": ".ref-arguments td, .ref-description", + "text": ".contents p, .contents li" + }, + "articles": { + "lvl0": { + "selector": ".contents h1" + }, + "lvl1": { + "selector": ".contents .name" + }, + "lvl2": { + "selector": ".contents h2, .contents h3", + "default_value": "Context" + }, + "text": ".contents p, .contents li, .tempate-article .contents .pre" + } }, "selectors_exclude": [ ".dont-index" - ] + ], + "min_indexed_level": 2, + "custom_settings": { + "separatorsToIndex": "_", + "attributesToRetrieve": [ + "hierarchy", + "content", + "anchor", + "url", + "url_without_anchor" + ] + } } + diff --git a/docs/index.html b/docs/index.html index f3c2915..d14f826 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,38 +1,44 @@ - + Sparse Additive Interaction Learning • sail - - - - - + + + + + + + - +
-
+
+

R software package to fit sparse additive interaction models with the strong heredity property. Interactions are limited to a single exposure or environment variable. The following figure (based on simulated data) gives an idea of the situation our method is trying to capture:

@@ -98,8 +99,8 @@

Installation

You can install the development version of sail from GitHub with:

-
if (!require("pacman")) install.packages("pacman")
-pacman::p_install_gh("sahirbhatnagar/sail")
+
if (!require("pacman")) install.packages("pacman")
+pacman::p_install_gh("sahirbhatnagar/sail")

@@ -118,11 +119,11 @@

Y: a continuous response of length n
  • -E: an exposure variable of length n. Can be continous or categorical.
    +E: an exposure variable of length n. Can be continuous or categorical.
  • A basis expansion function f(X_j) to be applied to each column of X, for example
  • -
    f.basis <- function(x) splines::bs(x, degree = 5)
    +

    @@ -172,22 +173,20 @@

    Latest news

    -

    You can see the most recent changes to the package in the NEWS.md file

    +

    You can see the most recent changes to the package in the NEWS.md file

    Code of Conduct

    -

    Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

    +

    Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

    -
    -

    Site built with pkgdown.

    +

    Site built with pkgdown 1.4.1.

    - diff --git a/docs/news/index.html b/docs/news/index.html index 1a5a5bb..350eac5 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -1,6 +1,6 @@ - + @@ -8,28 +8,47 @@ Changelog • sail + - + - + + - + - + + - + + + + + - + + + + + + + + + + + + - + + - - @@ -50,14 +65,15 @@ - + + + diff --git a/docs/reference/createfolds.html b/docs/reference/createfolds.html index adfa8a8..b2783f7 100644 --- a/docs/reference/createfolds.html +++ b/docs/reference/createfolds.html @@ -1,6 +1,6 @@ - + @@ -8,32 +8,50 @@ Create CV Folds — createfolds • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -54,14 +68,15 @@ - + + + diff --git a/docs/reference/cv.lspath.html b/docs/reference/cv.lspath.html index 4869146..1f3987d 100644 --- a/docs/reference/cv.lspath.html +++ b/docs/reference/cv.lspath.html @@ -1,6 +1,6 @@ - + @@ -8,32 +8,50 @@ Compute cross validation error — cv.lspath • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -54,14 +68,15 @@ - + + + diff --git a/docs/reference/cv.sail.html b/docs/reference/cv.sail.html index ab9cc75..15bd0b0 100644 --- a/docs/reference/cv.sail.html +++ b/docs/reference/cv.sail.html @@ -1,6 +1,6 @@ - + @@ -8,32 +8,50 @@ Cross-validation for sail — cv.sail • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -54,14 +68,15 @@ - + + + diff --git a/docs/reference/design_sail.html b/docs/reference/design_sail.html index 7e5a107..528c52a 100644 --- a/docs/reference/design_sail.html +++ b/docs/reference/design_sail.html @@ -1,6 +1,6 @@ - + @@ -8,31 +8,49 @@ Sail design matrix — design_sail • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -53,14 +67,15 @@ - + + + diff --git a/docs/reference/gendata.html b/docs/reference/gendata.html index e6a9d54..3c3a1b9 100644 --- a/docs/reference/gendata.html +++ b/docs/reference/gendata.html @@ -1,6 +1,6 @@ - + @@ -8,33 +8,51 @@ Simulation Scenario from Bhatnagar et al. (2018+) sail paper — gendata • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -55,14 +69,15 @@ - + + + diff --git a/docs/reference/gendataPaper.html b/docs/reference/gendataPaper.html index 5831601..d2de0b6 100644 --- a/docs/reference/gendataPaper.html +++ b/docs/reference/gendataPaper.html @@ -1,39 +1,57 @@ - + -Simulation Scenarion from Bhatnagar et al. (2018+) sail paper — gendataPaper • sail +Simulation Scenario from Bhatnagar et al. (2018+) sail paper — gendataPaper • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -54,14 +68,15 @@ - + + + diff --git a/docs/reference/plot.sail.html b/docs/reference/plot.sail.html index ac672a1..b395ff0 100644 --- a/docs/reference/plot.sail.html +++ b/docs/reference/plot.sail.html @@ -1,6 +1,6 @@ - + @@ -8,33 +8,51 @@ Plot Method for <code>sail</code> object — plot.sail • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -55,14 +69,15 @@ - + + + diff --git a/docs/reference/plotInter.html b/docs/reference/plotInter.html index 34757a0..4e83bc5 100644 --- a/docs/reference/plotInter.html +++ b/docs/reference/plotInter.html @@ -1,6 +1,6 @@ - + @@ -8,34 +8,52 @@ Plot Interaction Effects from sail object — plotInter • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + linear predictor. Currently only implemented for type="gaussian"" /> + + - + + - - @@ -56,14 +70,15 @@ - + + + diff --git a/docs/reference/plotMain.html b/docs/reference/plotMain.html index 15ef2db..c96d7ad 100644 --- a/docs/reference/plotMain.html +++ b/docs/reference/plotMain.html @@ -1,6 +1,6 @@ - + @@ -8,34 +8,52 @@ Plot Estimated Component Smooth Functions for Main Effects — plotMain • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + linear predictor. Currently only implemented for type="gaussian"" /> + + - + + - - @@ -56,14 +70,15 @@ - + + + diff --git a/docs/reference/predict.cv.sail.html b/docs/reference/predict.cv.sail.html index 8136021..d8975f1 100644 --- a/docs/reference/predict.cv.sail.html +++ b/docs/reference/predict.cv.sail.html @@ -1,6 +1,6 @@ - + @@ -8,33 +8,51 @@ Make predictions from a <code>cv.sail</code> object — predict.cv.sail • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -55,14 +69,15 @@ - + + + diff --git a/docs/reference/predict.sail.html b/docs/reference/predict.sail.html index 9dff250..3279d16 100644 --- a/docs/reference/predict.sail.html +++ b/docs/reference/predict.sail.html @@ -1,6 +1,6 @@ - + @@ -8,32 +8,50 @@ Make predictions from a sail object — predict.sail • sail + - + - + + - + - + + - + + + + + - - + + + + + + + + + + + + - + + - - @@ -54,14 +68,15 @@