SOMevidence is an R package for auditing whether classifications derived from
self-organizing maps (SOMs) meet prespecified evidence requirements under an
explicit analysis design. It is intended for ecological, environmental, and
evolutionary data in which sampling groups, monitoring domains, repeated
observations, multiple data layers, and incomplete transferability are common.
The package uses kohonen as its
SOM training backend. Its contribution is an evidence workflow around SOM
training: explicit data design, leakage-safe preprocessing, controlled
ensembles, partition stability, cross-model agreement, transfer diagnostics,
and conditional decisions that can abstain when evidence is insufficient.
The validation scope
distinguishes software checks, design-conditioned reproducibility, worked
examples, and external validation.
This separation is deliberate. SOMevidence does not select a universal best
map, force ecological class names, or turn unsupervised agreement into evidence
of ecological truth.
"abstain" outcome; andDirections below are diagnostic tendencies within otherwise comparable data, preprocessing, scopes, and model budgets. They are not universal thresholds and should not be combined into an automatic leaderboard.
| Question | Metrics | Diagnostic direction | Required evidence | Does not establish |
|---|---|---|---|---|
| How well does a fitted map represent its analysis data? | Quantization error, topographic error, empty-unit rate | Generally lower within comparable fits; inspect trade-offs | Successful fits using the same variables, preprocessing, scope, and comparable grids | A best map, a true number of classes, or ecological validity |
| Is the continuous SOM topology reproducible across fitted maps? | Rank correlation of shortest-hop sample-pair distances; optional tie-preserving neighbourhood Jaccard | Higher concordance under the prespecified fit-pair design; inspect coverage and unevaluable cases | Common sample IDs, comparable scopes, successful mappings, and an explicit exact-computation budget | Interchangeable codebooks, a best map, discrete classes, or independent inferential replication |
Is a fixed-k partition reproducible across the planned ensemble? |
Pairwise ARI/AMI, clusterwise Jaccard, joint coverage, complete-partition rate | Agreement and coverage higher; every source partition retains k
|
At least two successful, comparable partitions with adequate shared observations | That discrete types exist, that k is optimal, or that labels are correct |
| How consistently is each sample assigned? | Membership support, assignment entropy, assignment, consensus-label, and replicated coverage | Support and coverage higher; entropy lower | An identifiable consensus with repeated assignments and explicit coverage | A posterior probability or probability that an assignment is correct |
| Do controlled reference algorithms agree with the SOM partition? | Method-specific SOM-to-reference ARI, method count, reference-fit success | Agreement higher, with all requested methods evaluable | Prespecified reference methods fitted on common splits and preprocessing | Accuracy, independence of evidence, or ecological validation |
| Does the representation map comparably to a held-out domain? | Assessment-to-analysis distance ratio, unoccupied-unit rate, mapping coverage | Ratio nearer 1, unoccupied rate lower, coverage higher; inspect all fits | Genuine held-domain rows mapped using training-derived preprocessing | Predictive accuracy, causal explanation of shift, or general transferability |
| Are conclusions sensitive to prespecified analysis choices? | Scenario ARI/AMI, shared- and all-members Jaccard, contrast coverage | Agreement and coverage higher across the stated scenarios | Stable sample IDs, prespecified scenarios, and adequate shared observations | Robustness to unexamined choices or a probability that membership is correct |
| Does a consensus agree with labels excluded from training? | External-label ARI/AMI, contingency and composition tables | Agreement higher among evaluable samples | Labels kept outside training and joined by stable sample identity | Classification accuracy, ecological ground truth, or causation |
| Did a candidate meet the analyst's evidence requirements? |
supported, abstain, uncertain, and the individual gate checks |
All specified checks pass; failures abstain; unavailable evidence is uncertain | Prespecified thresholds and complete evidence from the same workflow | The existence of discrete ecological types or universal scientific defensibility |
SOMevidence calculates AMI with chance adjustment from the expected mutual information and uses the arithmetic mean of the two partition entropies as its normalizer. Software that uses a different AMI normalization can return a different numerical value for the same pair of partitions.
Representation-level checks alone cannot support a hard partition. A supported
decision requires traceable comparative partition evidence and at least one
prespecified partition-quality requirement. Otherwise the missing requirement
is reported as unavailable and assess_defensibility() returns "uncertain".
Install the current release from R-universe:
options(repos = c(
shaowen_ye = "https://shaowen-ye.r-universe.dev",
CRAN = "https://cloud.r-project.org"
))
install.packages("SOMevidence")
Install the source currently on GitHub with pak:
# install.packages("pak")
pak::pak("shaowen-ye/SOMevidence")
The following small run varies the resample, map grid, and random start. Its settings are deliberately modest for an interactive example; a scientific analysis should justify a larger, prespecified model budget.
library(SOMevidence)
dat <- simulate_som_scenario("clusters", n = 120, p = 6, seed = 1)
splits <- som_resamples(
dat,
method = "subsample",
repeats = 5,
prop = 0.9,
seed = 2
)
spec <- som_spec(
grids = list(c(4, 3), c(5, 4)),
seeds = c(3, 4),
rlen = 50,
k = 2:4
)
result <- run_som_workflow(
dat,
spec,
splits,
cross_models = c("kmeans", "ward")
)
result$audit$grid_summary
result$partitions$stability
result$consensus$k3$cluster_summary
result$cross_comparison$summary
summary(result)
result$consensus_failures
# Compare one prespecified pair of successful SOM representations.
successful_ids <- vapply(
Filter(function(fit) isTRUE(fit$success), result$ensemble$fits),
`[[`, character(1), "id"
)
representation <- audit_som_representation(
result$ensemble,
pairs = data.frame(
fit_a = successful_ids[[1]],
fit_b = successful_ids[[2]]
),
neighbourhood_size = 10
)
representation$pairwise
The workflow reports every requested candidate k; it does not silently pick
one. Gaussian mixture-model comparison is available when the suggested package
mclust is installed and "gmm" is requested explicitly.
audit_som_representation() is experimental and descriptive: it does not
score, rank or select maps, and its fit pairs and sample pairs are not treated
as independent replicates.
Separate predictors from sampling-design fields before constructing the analysis object. Numeric site codes, coordinates, dates, depths, and external class labels should not enter the SOM merely because they are numeric. The placeholder path below belongs in a separate, controlled analysis project; do not copy confidential study data into the package source repository.
raw <- read.csv("data/your-analysis-ready-data.csv", check.names = FALSE)
predictors <- c("temperature", "oxygen", "conductivity", "total_nitrogen")
dat <- som_data(
x = raw[predictors],
id = raw$sample_id,
group = raw$site_id,
time = raw$sampling_date,
domain = raw$survey_campaign
)
# Illustrative settings only: choose these from the sampling design and a
# prespecified computation budget for the study at hand.
splits <- som_resamples(
dat,
method = "group_subsample",
repeats = 20,
prop = 0.8,
seed = 2026
)
spec <- som_spec(
grids = list(c(7, 5), c(8, 6)),
seeds = 1:10,
rlen = 1000,
k = 2:8
)
result <- run_som_workflow(
dat,
spec,
splits,
cross_models = c("kmeans", "ward")
)
summary(result)
Choose resampling from the observation hierarchy, not from convenience:
| Data structure | Starting design |
|---|---|
| Independent observations | subsample |
| Repeated observations within sites or subjects | group_subsample |
| Prespecified spatial or temporal blocks | block_subsample |
| Transfer across campaigns, regions, or instruments | leave_domain_out |
| A protocol-defined split | custom |
This table is a starting point rather than an automatic rule. Dependence, sample size, domain coverage, transformations, missingness, and the scientific question still require study-specific decisions. Inspect the workflow summary, all failure and warning tables, and the separate evidence streams before interpreting any partition.
launch_som_app() returns a shiny.appobj, which can be printed in an
interactive R session or passed to shiny::runApp(). SOMevidence adds no
telemetry. When the app runs in a local R session, a selected CSV remains on the
local computer. If the app is deployed on a remote Shiny host, selecting a file
transfers it to that host; users should follow the host operator's access and
data-handling controls. The application helps configure and inspect a workflow,
but it does not return an analysis object. The YAML export is a configuration
snapshot. The exported R script can be rerun, but neither export replaces the
exact input data, package versions, warnings, failures, and results required for
a reproducible analysis record.
The package website contains five executable tutorials:
open_data_registry() lists the implemented tutorial source and additional
curated candidate datasets for ecological, environmental, and evolutionary
examples. Candidate datasets are not claimed to be package validation data and
are never downloaded during installation or package checks.
For a scientific analysis, retain at least:
SOMevidence version and sessionInfo();Persisted public som_* objects carry a structural contract version.
upgrade_som_object() can make only deterministic migrations supported by
retained evidence; it asks for recomputation when a scientifically important
field cannot be recovered. The object contract is not a substitute for the
package version, input provenance or sessionInfo().
Package-level checks reduce software errors, but they do not establish that a
sampling design, candidate k, ecological interpretation, or threshold is
appropriate for a particular study.
Use citation("SOMevidence") for the current citation. Questions and bug
reports are handled through GitHub Issues;
please read SUPPORT.md before filing a report. Contributions are
welcome under the process in CONTRIBUTING.md.
SOMevidence is distributed under the GNU General Public License version 3 or
later. See LICENSE.md.