plsi.logistic.auto: Partial linear single index logistic regression with...

View source: R/plsi.logistic.auto.R

plsi.logistic.autoR Documentation

Partial linear single index logistic regression with automatic smoothness selection

Description

Binary-outcome analog of plsi.lr.auto(): same partial linear single index model, but with a logistic link. The link function is estimated with a penalized regression spline (mgcv::gam, family = binomial(), REML smoothing-parameter selection), so there is no spline.num to hand-tune, only an upper bound k on basis complexity, with REML shrinking unneeded wiggliness toward a straight line on the logit scale.

Usage

plsi.logistic.auto(
  data,
  Y.name,
  X.name,
  Z.name,
  k = 10,
  bs = "cr",
  initial.random.num = 5,
  seed = 2026
)

Arguments

data

A data set including all needed variables

Y.name

Variable name for the binary outcome. Must be coded 0/1, or a 2-level factor (which will be coerced to 0/1 by level order, with a message reporting which level became 0 and which became 1).

X.name

Variable name vector for exposures

Z.name

Variable name vector for confounders

k

Upper bound on basis dimension for the smooth link function. Default 10.

bs

Smooth basis type passed to mgcv::s(); default "cr" (cubic regression spline).

initial.random.num

Number of random initials for the single-index direction search

seed

A single integer used to seed the RNG so results (random initials and downstream optim() convergence) are reproducible. Set to NULL to skip seeding and use whatever RNG state is already active in the calling environment. Default is 2026.

Details

Because the outcome is binary, the "confounder-free" single-index model cannot be built by subtracting confounder effects from y on the response scale the way plsi.lr.auto() does (probabilities aren't additive), and it cannot be built by residualizing the full model's own fitted linear predictor either, that would leave a value that is already an exact smooth function of the single index, so refitting a smooth to it would just retrace the same curve with near-zero (and spuriously tiny) standard errors. Instead, the confounder contribution from the full model is fixed as a known offset() and a second, confounder-free binomial gam is refit directly against the actual observed y, preserving real binomial sampling variability. Predictions from this model are made at offset = 0, consistent with how the offset was netted out of every training point.

Value

A list of model estimation and prediction results, structured analogously to plsi.lr.auto()'s output:

  • si.coefficient: Single-index direction estimates and inference.

  • confounder.coefficient: Confounder log-odds coefficients, plus odds ratios and their 95% CIs.

  • si.fun: The estimated single-index link function, on both the logit scale (fit/se/lwr/upr) and the probability scale (prob.fit/prob.lwr/prob.upr), obtained by back-transforming the logit-scale CI so it stays between 0 and 1.

  • si.fun.model: A confounder-free gam of the logit-scale residual on the single index alone, predict() from this needs only single_index_estimated, not the original confounders. See Details.

  • full.model: The full fitted gam (smooth + confounders), kept for reference/diagnostics.

Author(s)

Yuyan Wang

Examples

## Not run: 
data(nhanes.new)
data <- nhanes.new

X.name <- c("X1_trans.b.carotene", "X2_retinol", "X3_g.tocopherol", "X4_a.tocopherol",
            "X5_PCB99", "X6_PCB156", "X7_PCB206",
            "X8_3.3.4.4.5.pncb", "X9_1.2.3.4.7.8.hxcdf", "X10_2.3.4.6.7.8.hxcdf")
Z.name <- c("AGE.c", "SEX.Female", "RACE.NH.Black",
           "RACE.MexicanAmerican", "RACE.OtherRace", "RACE.Hispanic" )

# demo binary outcome (illustrative only as nhanes.new has no native binary variable).
 Simulated from a *true* single-index combination of the exposures, run through a
 nonlinear logit link, plus a confounder effect, and drawn as genuine Bernoulli noise
 (not a hard threshold on an existing variable), a hard threshold produces near-perfect
 separation and destabilizes the fit, whereas real classification uncertainty is both
 more realistic and numerically well-behaved.

set.seed(2026)
beta_true <- c(0.30, -0.20, 0.10, 0.40, -0.30, 0.20, -0.10, 0.25, -0.15, 0.35)
beta_true <- beta_true / sqrt(sum(beta_true^2))
x_std <- scale(data[, X.name])
single_index_true <- as.vector(x_std %*% beta_true)
log_odds <- -0.2 + 0.5 * sin(single_index_true) + 0.05 * data$AGE.c
data$high.triglyceride <- stats::rbinom(nrow(data), size = 1, prob = stats::plogis(log_odds))

Y.name <- "high.triglyceride"

k <- 10
bs <- "cr"
initial.random.num <- 1
seed <- 2026

model_logistic_auto <- plsi.logistic.auto(data = data, Y.name = Y.name, X.name = X.name,
                      Z.name = Z.name, k = k, bs = bs,
                      initial.random.num = initial.random.num, seed = seed)

## End(Not run)


EPLSIM documentation built on Nov. 5, 2026, 1:08 a.m.