Constructs interpretable latent variables from communities in
squared-association networks. Supports full, partial, and semipartial
associations, feature selection, sparse networks, inference, prediction,
visualization, and supervised regression. The generalized method is
described in Kosztyan et al. (2024)
nda constructs interpretable latent variables from communities in
squared-association networks. It supports unsupervised dimensionality
reduction with ndr() and supervised modelling with ndrlm().
Version 0.3.0 adds faster and safer association calculations, sparse and parallel workflows, fixed memberships, inference and bootstrap diagnostics, new centrality definitions, prediction methods, configurable graphics, and ordinary least squares, ridge, elastic-net, and LOESS response engines.
Install the development version from GitHub:
remotes::install_github("kzst/nda")
library(nda)
ndr()ndr():
fit <- ndr(
swiss,
cor_method = "spearman",
cor_type = "full",
centrality = "pagerank",
min_comm = 2,
seed = 42
)
fit
summary(fit)
round(fit$loadings, 3)
# Score new observations with the training transformation.
predict(fit, swiss[1:5, , drop = FALSE])
Network and biplot functions return printable objects. Assignment is silent; print the object to render it.
network <- plot(
fit,
interactive = FALSE,
show_weights = TRUE,
shape = "automatic"
)
network
# The same visual grammar as an embedded interactive HTML widget.
interactive_network <- plot(fit, interactive = TRUE, show_weights = TRUE)
interactive_network
score_plot <- biplot(fit, view_3D = FALSE, interactive = FALSE)
score_plot
Community membership is shown with a light qualitative node-colour palette. Indicators use one common rectangular shape by default; positive and negative associations use green and red edges, and absolute association controls edge width. Shapes, colours, line types, and the minimum/maximum width remain configurable.
covar = TRUE accepts an arbitrary square similarity matrix. For example,
NDR can cluster observations from normalized Euclidean similarities:
z <- scale(swiss)
d <- as.matrix(dist(z))
similarity <- 1 - d / max(d)
cluster_fit <- ndr(similarity, covar = TRUE, seed = 42)
table(cluster_fit$membership)
Important options include:
ndrlm()ndrlm() connects original or NDA-reduced predictors to original or
NDA-reduced responses. Set latents to "none", "in", "out", or
"both".
The example below uses the two-community latent input structure from the
published low-sample-size mtcars application:
X <- mtcars[, setdiff(names(mtcars), "mpg")]
Y <- mtcars["mpg"]
membership <- c(
cyl = 1, disp = 2, hp = 1, drat = 2, wt = 2,
qsec = 1, vs = 1, am = 2, gear = 2, carb = 1
)
model <- ndrlm(
Y,
X,
latents = "in",
optimize = FALSE,
regression = "lm",
membership.X = membership,
seed = 42
)
summary(model)
predict(model, X[1:5, , drop = FALSE])
head(fitted(model))
head(residuals(model))
For regression = "lm", each model$fits[[i]] is a genuine lm object and
can be used directly with summary(), AIC(), BIC(), and
lm.beta::lm.beta().
inherits(model$fits[[1]], "lm")
summary(model$fits[[1]])
Ridge and elastic net use glmnet and retain NDRLM engine wrappers:
ridge <- ndrlm(
Y,
X,
latents = "none",
optimize = FALSE,
regression = "ridge",
lambda = 0.1
)
predict(ridge, X[1:5, , drop = FALSE])
The package methods also accept legacy direct lm fits and early 0.3.0
wrapped lm fits. For engine-independent code, use summary(), predict(),
fitted(), residuals(), and plot() on the enclosing ndrlm object.
static_paths <- plot(
model,
interactive = FALSE,
shape = "automatic"
)
static_paths
interactive_paths <- plot(
model,
interactive = TRUE,
show_edge_labels = TRUE
)
interactive_paths
Observed variables are rectangles and latent variables are circles. Each
latent variable and its indicators share one light community colour. Positive
paths are green, negative paths are red, and absolute standardized coefficient
or loading magnitude controls width within its edge role. The plot computes
standardized structural coefficients for ordinary linear, ridge, and
elastic-net regression from the complete training observations; use
standardized.paths = FALSE only when raw coefficients are required.
Measurement links between
observed and latent variables are dashed; structural paths are solid. Latent
nodes are centred on their indicator groups, absent layers leave no empty
horizontal column, and the default node fills are slightly translucent and
lightened. Edge labels use a light background offset from the path to avoid
overwriting thick lines. For legacy
unnamed fit lists, the path target is recovered from the fitted response
formula before any original-variable fallback is considered; standardized
coefficients are reconstructed from the legacy fitted model.
Static plots use the package's layered grid renderer by default. The legacy
igraph renderer remains available with static.engine = "igraph". Both static
and interactive variants are printable objects, so the following pattern
works with screen and file devices:
p <- plot(model, interactive = FALSE) # no drawing during assignment
p # draw now
pdf("ndrlm-paths.pdf", width = 10, height = 6)
p
dev.off()
Expensive NSGA-II optimization is optional:
optimized <- ndrlm(
Y,
X,
latents = "in",
regression = "lm",
target = "adj.r.square",
popsize = 20,
generations = 50,
restarts = 3,
seed = 42
)
plot(
optimized$NSGA_trace$evaluation,
optimized$NSGA_trace$best_target,
type = "s",
xlab = "Objective evaluation",
ylab = "Best target value"
)
| Purpose | Functions |
|---|---|
| Structured example data | data_gen() |
| Global, row, or column scaling | normalize() |
| Distance covariance and correlation | dCov(), dCor() |
| Partial and semipartial distance correlation | pdCor(), spdCor() |
| KMO-based feature selection | fs.KMO() |
| Loading-based feature selection and iterative refitting | fs.dimred() |
The source package builds three official vignettes:
nda-function-tour: a visual tour of the package;ndr-workflow: the generalized NDR workflow;ndrlm-workflow: supervised latent-variable regression.List or open them from an installed package with:
vignette(package = "nda")
vignette("nda-function-tour", package = "nda")
vignette("ndr-workflow", package = "nda")
vignette("ndrlm-workflow", package = "nda")
seed whenever community detection, bootstrap inference, or NSGA-II is
involved.n_boot and optimization settings while developing, then increase
them for final analysis.sparsecalc = TRUE is useful after meaningful edge thresholding.Kosztyan, Z. T., Kurbucz, M. T., and Katona, A. I. (2022). Network-based dimensionality reduction of high-dimensional, low-sample-size datasets. Knowledge-Based Systems, 109180. https://doi.org/10.1016/j.knosys.2022.109180
Kosztyan, Z. T., Katona, A. I., Kurbucz, M. T., and Lantos, Z. (2024). Generalized network-based dimensionality analysis. Expert Systems with Applications, 238, 121779. https://doi.org/10.1016/j.eswa.2023.121779
Zsolt T. Kosztyan, Marcell T. Kurbucz, Attila I. Katona, and Zahid Khan.