Select and assemble final response deliveries
aggregateResponses.RdCombine unseen ensemble point predictions with reconstructed training-row
OOF predictions, add signed residual offsets, select one candidate per
sample and response by cell R2, and write delivery/feature products. This
final selector is distinct from predictModel()'s response-level
RMSE-or-R2 selector.
Usage
aggregateResponses(
.path.summary,
.path.export,
.path.datasets,
key,
responses,
datasets,
boundsMin = -Inf,
boundsMax = Inf,
.path.iter = NULL
)Arguments
- .path.summary
Existing directory containing the four summary inputs described in Input tables.
- .path.export
Existing writable output directory. It is not created by this helper.
Yo.csv,X.csv, andXo.csvare assigned here.- .path.datasets
Directory containing assembled
dataset.csvinputs used only for feature exports.- key
A non-empty character key name used when extracting feature tables. Response aggregation itself is hard-coded to
SampleID; setting another key does not replace that requirement.- responses
Non-empty character vector excluded, with
set, from feature columns inX.csvandXo.csv.- datasets
Non-empty character vector of assembled dataset basenames. Feature extraction uses the last declared file that actually exists.
- boundsMin, boundsMax
Numeric response bounds used to project every point-plus-offset value. Their order and finiteness are not validated.
- .path.iter
NULL, or an iteration directory. When non-null, its parent path forY.csvis created recursively and the training-row median-offset table is written or merged.
Value
Invisibly, NULL. Results are Yo.csv, optional
Y.csv, and the feature files written under the rules above.
Input tables
The helper stops unless response_long.csv, metrics.csv, and
prediction_quantiles.csv exist. It then separately requires
residuals_oof.csv.
response_long.csvmust provideSampleID,value,method,dataset, andresponse. Only rows withmethod == "ensemble.RMSE"are retained and marked as unseen rows.residuals_oof.csvmust provideSampleID,y_hat_oof,dataset, andresponse. Every row is converted to a training candidate withvalue = y_hat_oofand methodensemble.RMSE.metrics.csvmust providemethod,response,dataset, andr2. Onlyensemble.RMSEmetric rows enter.prediction_quantiles.csvmust provideresponse,dataset,q_50,q_90, andq_95.
Extra columns can propagate through joins. Missing, duplicate, or incompatible keys retain data.table join behavior; no uniqueness assertion is made.
Offset construction and final selector
Metric and offset rows are joined to every unseen or training candidate by
response and dataset. Let \(i\) index SampleID, \(r\) a
response, \(d\) a joined candidate dataset, and
\(p\in\{0.50,0.90,0.95\}\) an offset probability. Let
\(\hat y_{ird}\) be a candidate point value and \(q_{p,rd}\) its signed
OOF-residual offset, all in response units. Let \(a\) and \(b\) be the
bounds supplied by boundsMin and boundsMax, respectively.
When \(a\le b\), define interval projection by
\(\Pi_{[a,b]}(z)=\min\{b,\max\{a,z\}\}\) for real \(z\). The helper
computes
$$Q_{p,ird}=\Pi_{[a,b]}\{\hat y_{ird}+q_{p,rd}\}.$$
These are projected point-plus-offset estimates, not calibrated predictive
quantiles or intervals. Bound order and finiteness are not checked; with
invalid bounds the nested minimum/maximum is still executed but is not an
interval projection.
For each (SampleID, response), all RMSE-ensemble candidates are
ordered by descending joined cell r2; the first row is selected and
supplies one dataset for all three probabilities:
$$d^*_{ir}=\operatorname*{first\,argmax}_{d}R^2_{rd}.$$
The score is cell-level even though selection is grouped by sample.
Ties follow joined-row order. Finite scores precede missing scores; when all
joined scores in a group are missing, the first joined row is still selected
with missing r2. Missing offsets propagate missing delivery values
because this helper does not remove them. This selector never considers
ensemble.R2 rows and is not the response-level metric selector used
by predictModel(). Therefore modelPipeline(ensemble = ) does not
change the final candidate family assembled here.
Delivery and iteration products
The selected table is expanded to long probabilities p = 0.50,
0.90, and 0.95. It retains available identifier columns from
SampleID, HoleID, From, and To, followed by
response, p, value, r2, and dataset.
Response values and offsets share response units; r2 and p
are dimensionless.
Unseen rows are written to Yo.csv. If that file exists, every old row
whose response occurs in the current unseen result is removed, current rows
are appended, and other responses are preserved. Replacement is by response,
not dataset.
When .path.iter is non-null, training rows at p = 0.50 are
cast to Y.csv with one response column per SampleID. On merge,
new response columns replace same-named old columns and old non-overlapping
response columns remain. Thus Y.csv contains median signed-offset
estimates; p = 0.50 is not necessarily the unadjusted point value.
Feature products, conditions, and return
Among declared assembled files that exist, the last one is read. Every
column except key, the declared responses, and set is treated
as a feature. Rows with set == "train" write X.csv; rows with
set == "predict" write Xo.csv. If no assembled file exists, a
warning is emitted and neither feature file is written. If no feature column
remains, a warning is emitted but key-only files are still written.
Assigned CSVs are overwritten and writes are not transactional. Required file, column, join, cast, and directory errors propagate after any earlier writes. Valid progress is sent through ssel's debug channel, which emits only when global verbose is enabled and quiet is disabled. The helper uses no random numbers.
References
Parikh, N., and Boyd, S. (2014). Proximal Algorithms. Foundations and Trends in Optimization, 1(3), 127–239. doi:10.1561/2400000003 .
See also
predictModel() for cell evaluation and the first selector,
auditQuantiles() for signed residual offsets, and chainPipeline() for
the consumer of optional Y.csv.
Examples
root <- tempfile("ssel-aggregate-")
summary_dir <- file.path(root, "summary")
export_dir <- file.path(root, "export")
datasets_dir <- file.path(root, "datasets")
iter_dir <- file.path(root, "iter")
for (path in c(summary_dir, export_dir, datasets_dir)) {
dir.create(path, recursive = TRUE)
}
data.table::fwrite(
data.table::data.table(
SampleID = rep(c("P1", "P2"), each = 2),
value = c(10, 20, 11, 21),
method = "ensemble.RMSE",
dataset = rep(c("d1", "d2"), 2),
response = "target"
),
file.path(summary_dir, "response_long.csv")
)
data.table::fwrite(
data.table::data.table(
method = "ensemble.RMSE", response = "target",
dataset = c("d1", "d2"), r2 = c(0.5, 0.9)
),
file.path(summary_dir, "metrics.csv")
)
data.table::fwrite(
data.table::data.table(
response = "target", dataset = c("d1", "d2"),
q_50 = c(0, 1), q_90 = c(1, 2), q_95 = c(2, 3)
),
file.path(summary_dir, "prediction_quantiles.csv")
)
data.table::fwrite(
data.table::data.table(
response = "target", dataset = c("d1", "d2"),
rowIndex = 1L, SampleID = "S1",
y_obs = c(8, 18), y_hat_oof = c(9, 19), residual = -1
),
file.path(summary_dir, "residuals_oof.csv")
)
for (dataset in c("d1", "d2")) {
data.table::fwrite(
data.table::data.table(
SampleID = c("S1", "P1", "P2"),
set = c("train", "predict", "predict"),
feature = 1:3
),
file.path(datasets_dir, paste0(dataset, ".csv"))
)
}
aggregateResponses(
.path.summary = summary_dir,
.path.export = export_dir,
.path.datasets = datasets_dir,
key = "SampleID",
responses = "target",
datasets = c("d1", "d2"),
.path.iter = iter_dir
)
data.table::fread(file.path(export_dir, "Yo.csv"))
#> SampleID response p value r2 dataset
#> <char> <char> <num> <int> <num> <char>
#> 1: P1 target 0.50 21 0.9 d2
#> 2: P2 target 0.50 22 0.9 d2
#> 3: P1 target 0.90 22 0.9 d2
#> 4: P2 target 0.90 23 0.9 d2
#> 5: P1 target 0.95 23 0.9 d2
#> 6: P2 target 0.95 24 0.9 d2
data.table::fread(file.path(iter_dir, "Y.csv"))
#> SampleID target
#> <char> <int>
#> 1: S1 20
# Dataset d2 wins because its RMSE-ensemble cell has the larger R2.
unlink(root, recursive = TRUE)