Compute SHAP-based feature contributions to the concentration index of a predicted outcome. The SHAP table can be supplied either in wide format (one row per observation, one column per feature) or in DALEX-like long format and reshaped internally.
Arguments
- shap
A rectangular SHAP table. By default this should be a wide table with one numeric feature column per SHAP contributor. If
from_dalex = TRUE,shapshould instead be a long DALEX-like table containing observation IDs, feature names, and SHAP values.- rank
A numeric vector giving the socioeconomic ranking variable for each observation. When
type = "L", this is interpreted as the observed socioeconomic level variable.- type
One of
"CI","CIg","CIc", or"L"selecting the decomposition target. The first three are rank-dependent concentration indices scored consistently withci_factory()."L"uses the Erreygers–Kessels level-dependent bivariate index based on observed socioeconomic levels.- prediction
Optional numeric vector of model predictions. If omitted, predictions are reconstructed as
baseline + rowSums(shap).- baseline
Optional scalar baseline prediction. Required when
predictionis not supplied.- weights
Optional numeric vector of non-negative case weights. If omitted, equal weights are used. Observations with non-positive weights do not contribute to the decomposition.
- from_dalex
Logical scalar. If
TRUE, reshape a DALEX-like long SHAP table to wide format before decomposition.- dalex_id_col
Optional column name identifying observations in the DALEX-like input.
- dalex_variable_col
Optional column name containing feature names in the DALEX-like input.
- dalex_value_col
Optional column name containing SHAP values in the DALEX-like input.
- na_rm
Logical scalar. If
TRUE, drop rows with missing values in required inputs before computing the decomposition.- sort
Logical scalar. If
TRUE, order output features by decreasing absolute SHAP contribution.- tolerance
Numeric tolerance used to detect numerically zero mean predictions or concentration indices.
Value
A list of class "shap_ci_decomposition" with two components:
diagnostics, a one-row data.table of decomposition diagnostics, and
contributions, a data.table containing one row per SHAP feature with
columns feature, D_k_SHAP, pct_contribution, and
abs_contribution.
Details
The total concentration_index reported in diagnostics is the
non-negative score returned by ci_factory(type). Feature contributions
are computed on the signed linear scale for the selected index and then
oriented so they sum to the non-negative factory score when the SHAP values
reconstruct the prediction.
Percentage contributions are computed as 100 * D_k_SHAP / sum(D_k_SHAP),
matching the rineq convention of dividing each CI contribution by the
sum of all CI contributions. When SHAP values reconstruct the prediction,
this denominator is the total concentration-index score; otherwise,
additivity_gap records the difference.
For rank-dependent types, weighted fractional ranks and the same unbiased
weighted covariance convention used by ci_factory() are used. "CI"
divides feature covariances by the weighted mean prediction, "CIg" uses
the generalized covariance form, and "CIc" applies the prediction-range
correction.
For type = "L", rank is treated as an observed socioeconomic level
s_i. The decomposition uses the weighted mean of
((s_i - mu_s) / mu_s) * phi_ik for each feature, where mu_s is the
weighted mean socioeconomic level.
Examples
shap <- data.frame(
education = c(1, 0, -1),
water = c(0, 1, 1)
)
rank <- c(1, 2, 3)
res <- shap_conc_decomp(
shap = shap,
rank = rank,
baseline = 2
)
res$diagnostics
#> n weight_sum type mean_prediction concentration_index
#> <int> <num> <char> <num> <num>
#> 1: 3 3 CI 2.666667 0.08333333
#> signed_concentration_index score_direction shap_sum additivity_gap
#> <num> <num> <num> <num>
#> 1: -0.08333333 -1 0.08333333 1.387779e-17
#> centered_rank_sum prediction_source
#> <num> <char>
#> 1: 4.626155e-17 baseline + rowSums(shap)
res$contributions
#> feature D_k_SHAP pct_contribution abs_contribution
#> <char> <num> <num> <num>
#> 1: education 0.16666667 200 0.16666667
#> 2: water -0.08333333 -100 0.08333333
dalex_like <- data.frame(
"_id_" = rep(1:3, each = 3),
"_vname_" = rep(c("_baseline_", "education", "water"), times = 3),
"_attribution_" = c(2, 1, 0, 2, 0, 1, 2, -1, 1),
check.names = FALSE
)
shap_conc_decomp(
shap = dalex_like,
rank = rank,
baseline = 2,
from_dalex = TRUE
)$contributions
#> feature D_k_SHAP pct_contribution abs_contribution
#> <char> <num> <num> <num>
#> 1: education 0.16666667 200 0.16666667
#> 2: water -0.08333333 -100 0.08333333