Skip to contents

Run trainRegressionModel() in evaluation mode, collect its point predictions and OOF metrics, select one response–dataset cell per response, and add matching signed OOF-residual offsets. This is the first delivery selector. The later aggregateResponses() selector has a different candidate set and grouping rule.

Usage

predictModel(.path.train, .path.model, .path.metrics,
  .path.response, .path.summary, .path.export, .file.index = NULL,
  METHODS, PPROC = NULL, probs = c(0.50, 0.90, 0.95),
  .min = -Inf, .max = Inf, .ensemble = "ensemble.R2",
  .deliverable_datasets = NULL, .responses = NULL)

Arguments

.path.train

Path to an existing split directory. Training files are discovered non-recursively by the suffix _TRAIN.csv. Their first two underscore-separated fields are interpreted as response and dataset, so those identifiers cannot contain underscores.

.path.model

Existing directory containing the fitted model files required by trainRegressionModel() evaluation mode.

.path.metrics

Existing writable directory for cell metric CSVs. Evaluation can overwrite assigned files; this helper then reads every CSV in the directory and overwrites metrics.csv under .path.summary with their unique union.

.path.response

Existing writable directory for cell response CSVs. Evaluation can overwrite assigned files; matching files are then read to assemble the long prediction table.

.path.summary

Summary-output directory. It is created non-recursively when absent, so its parent must exist. A compatible prediction_quantiles.csv from auditQuantiles() must already exist.

.path.export

Export directory. It is created non-recursively when absent, so its parent must exist. Assigned dataset CSVs are overwritten.

.file.index

NULL, a nonexistent path, or a CSV index path. When an existing file is supplied, its first column is the join key used to rewrite every CSV under .path.summary and .path.export that contains that name.

METHODS

Non-empty character vector of fitted caret method identifiers. Duplicates are removed and order is randomized before evaluation.

PPROC

Forwarded as .preProcess to evaluation mode. The current trainRegressionModel() evaluation path does not use preprocessing.

probs

Numeric vector of offset probabilities. Each value is converted to an integer percentage with as.integer(100 * p) and requires a matching q_XX column in prediction_quantiles.csv. The standard producer writes only 0.50, 0.90, and 0.95.

.min, .max

Numeric response bounds. Base point predictions are projected by the evaluation engine; each point-plus-offset value is projected again. Bound order and finiteness are not validated.

.ensemble

A value in c("ensemble.R2", "ensemble.RMSE"). It selects both the metric and method label used by the response-level selector. The default is "ensemble.R2".

.deliverable_datasets

NULL, or a character vector restricting dataset eligibility only for response-level selection. It does not change split discovery, evaluation, long outputs, or the list of dataset-named files considered for export.

.responses

NULL, or a character vector restricting discovered responses before evaluation. NULL uses all parsed responses.

Value

Invisibly, a list with DTL, the unadjusted long point table; DTW, the selected wide point-plus-offset table; and DT.metrics, the deduplicated union of metric CSVs before any index rewrite.

Evaluation and assembly

Discovered response and dataset names are deduplicated independently and passed to trainRegressionModel() with TRAIN = FALSE. The method vector is sampled with R's current random-number generator, so this call advances RNG state even though fitted models are reused. The engine reconstructs OOF metrics and predicts unseen split rows according to its accepted reference contract. Because this wrapper does not override the engine's PARALLEL argument, evaluation registers a PSOCK backend with at most two workers, stops it on exit, and leaves foreach sequential. A restricted environment that forbids local server sockets can therefore fail before evaluation even though no model is fitted.

Every existing metric CSV is row-bound and deduplicated into DT.metrics. Every existing response_dataset.csv under .path.response is read, deduplicated, and tagged with set = "response_dataset". Their union, DTL, retains base-method and both ensemble point predictions. Missing response files are skipped. If none is read, cleanup of the never-created intermediate can error before a result is written.

Response-level selector and offsets

Let \(r\) index a response, \(d\) a dataset cell, \(x\) one unseen predictor row, and \(\mathcal D_r\) the eligible metric rows for response \(r\). Eligibility includes the requested ensemble label and, when supplied, membership in .deliverable_datasets. For the RMSE ensemble the selected row is $$d_r^{RMSE}=\operatorname*{first\,argmin}_{d\in\mathcal D_r} \mathrm{RMSE}_{rd},$$ among rows labeled ensemble.RMSE. For the R2 ensemble it is $$d_r^{R2}=\operatorname*{first\,argmax}_{d\in\mathcal D_r}R^2_{rd},$$ among rows labeled ensemble.R2. Missing scores are ignored when a non-missing score exists, and an extremum tie selects the first metric row. If every score in a response group is missing, or filtering leaves no row for that response, the selector contributes no selected row for it. Later offset assembly and reshaping can consequently omit that response or fail when no usable selection remains.

For the selected response and dataset, let \(\hat y_r(x)\) be the matching ensemble point prediction and let \(q_{p,rd}\) be the signed, cell-pooled OOF-residual offset at requested probability \(p\), written by auditQuantiles(). Let \(a\) and \(b\) be bounds in response units, supplied by .min and .max, respectively. When \(a\le b\), interval projection is \(\Pi_{[a,b]}(z)=\min\{b,\max\{a,z\}\}\) for real \(z\). The delivered value is $$Q_{p,r}(x)=\Pi_{[a,b]}\{\hat y_r(x)+q_{p,rd}\}.$$ This is a projected point-plus-residual-offset estimate. It is not a predictive-distribution quantile and carries no conditional, marginal, or conformal coverage guarantee. Exactly one matching offset row is required for every selected cell. Rows with any missing field are removed before wide reshaping. Bound order and finiteness are not checked; with invalid bounds the nested minimum/maximum remains the executed operation but is not an interval projection.

Files, index joins, and return

The helper overwrites metrics.csv with DT.metrics and response_long.csv with the unadjusted long point table DTL. For each discovered dataset, it finds sample IDs occurring in long-table set names ending in _dataset and writes a dataset-named CSV when at least one selected wide row has such an ID. Dataset names enter an unescaped regular expression. Each wide file has one row per retained sample/probability, a SampleID column, one column per selected response, and p. Existing assigned files are overwritten.

If an index file is supplied, every CSV currently present under both output directories is read. Files containing the index's first column are replaced by the index-to-file data.table join, which can add columns, change order, or duplicate rows when the key is not unique. This includes pre-existing CSVs not created by the current call. In-memory return tables precede these joins.

Errors from evaluation, absent quantile files or columns, non-unique selected rows, malformed schemas, empty casts, joins, and file operations can occur after earlier assigned files were written; there is no transactional rollback. Progress uses ssel's debug channel.

References

Hyndman, R. J., and Fan, Y. (1996). Sample quantiles in statistical packages. The American Statistician, 50(4), 361–365. doi:10.1080/00031305.1996.10473566 .

Parikh, N., and Boyd, S. (2014). Proximal Algorithms. Foundations and Trends in Optimization, 1(3), 127–239. doi:10.1561/2400000003 .

See also

trainRegressionModel() for evaluation and ensemble point predictions, auditQuantiles() for the offset estimator, and aggregateResponses() for the later RMSE-candidate rowwise selector.

Examples

# \donttest{
root <- tempfile("ssel-predict-")
train_dir <- file.path(root, "train")
model_dir <- file.path(root, "model")
metrics_dir <- file.path(root, "metrics")
response_dir <- file.path(root, "response")
summary_dir <- file.path(root, "summary")
export_dir <- file.path(root, "export")
for (path in c(train_dir, model_dir, metrics_dir, response_dir,
               summary_dir, export_dir)) {
  dir.create(path, recursive = TRUE)
}

train <- data.frame(
  x = 1:6,
  y = c(1, 2, 2, 4, 5, 7)
)
test <- data.frame(x = c(7, 8), SampleID = c("P1", "P2"))
utils::write.csv(train, file.path(train_dir, "target_demo_TRAIN.csv"),
                 row.names = FALSE)
utils::write.csv(test, file.path(train_dir, "target_demo_TEST.csv"),
                 row.names = FALSE)

fit <- stats::lm(y ~ x, data = train)
fit$pred <- data.frame(
  intercept = TRUE,
  pred = c(1.5, 1.5, 3, 3, 6, 6),
  obs = train$y,
  rowIndex = 1:6
)
fit$bestTune <- data.frame(intercept = TRUE)
saveRDS(fit, file.path(model_dir, "lm_target_demo.Rds"))
data.table::fwrite(
  data.table::data.table(
    response = "target", dataset = "demo", n = 6L,
    q_50 = 0, q_90 = 0.5, q_95 = 1
  ),
  file.path(summary_dir, "prediction_quantiles.csv")
)

set.seed(2026)
result <- suppressMessages(predictModel(
  .path.train = train_dir,
  .path.model = model_dir,
  .path.metrics = metrics_dir,
  .path.response = response_dir,
  .path.summary = summary_dir,
  .path.export = export_dir,
  METHODS = "lm",
  .ensemble = "ensemble.RMSE"
))
result$DTW
#> Index: <SampleID>
#>    SampleID   target     p
#>      <char>    <num> <num>
#> 1:       P1 7.600000  0.50
#> 2:       P2 8.771429  0.50
#> 3:       P1 8.100000  0.90
#> 4:       P2 9.271429  0.90
#> 5:       P1 8.600000  0.95
#> 6:       P2 9.771429  0.95
# p identifies three signed-residual offsets around one selected cell.

unlink(root, recursive = TRUE)
# }