Distance specifications
1 Overview
manydist provides tools for constructing dissimilarities/distances for numerical, categorical, and mixed-type data.
The main function is mdist(): the user can either specify the distance via a preset or customize it. The custom specification requires:
-
method_catcontrols the categorical dissimilarity; -
method_numcontrols the preprocessing of numerical variables; -
commensurablecontrols whether variable-wise contributions should be, on average, the same;
2 Setup
We use the palmerpenguins data for illustration.
if (requireNamespace("palmerpenguins", quietly = TRUE)) {
data("penguins", package = "palmerpenguins")
penguins_small <- palmerpenguins::penguins |>
dplyr::select(-year)|>
tidyr::drop_na()
}The data contain numerical variables, such as bill length and body mass, and categorical variables, such as island and sex.
skim_cols <- c(
"skim_type",
"skim_variable",
"complete_rate",
"numeric.mean",
"numeric.sd",
"factor.n_unique"
)
skimr::skim(penguins_small) |>
dplyr::as_tibble() |>
dplyr::select(dplyr::any_of(skim_cols)) |>
kableExtra::kbl(format = "html", digits = 2) |>
kableExtra::kable_styling(full_width = FALSE)| skim_type | skim_variable | complete_rate | numeric.mean | numeric.sd | factor.n_unique |
|---|---|---|---|---|---|
| factor | species | 1 | NA | NA | 3 |
| factor | island | 1 | NA | NA | 3 |
| factor | sex | 1 | NA | NA | 2 |
| numeric | bill_length_mm | 1 | 43.99 | 5.47 | NA |
| numeric | bill_depth_mm | 1 | 17.16 | 1.97 | NA |
| numeric | flipper_length_mm | 1 | 200.97 | 14.02 | NA |
| numeric | body_mass_g | 1 | 4207.06 | 805.22 | NA |
3 Computing a mixed-type dissimilarity
The simplest way to compute a mixed-type dissimilarity is to use a preset.
For example, the "gower" preset computes a Gower-type dissimilarity for mixed numerical and categorical data.
MDist object
preset : gower
number of observations : 333
number of continuous variables : 4
number of categorical variables : 2
parameters:
- commensurability adjustment: FALSE
The result is an MDist object. Internally, MDist is implemented as an R6 object, which stores the computed dissimilarity together with metadata and methods for extracting or reusing the result. The dissimilarity can be extracted as a standard dist object using to_dist(). For display, we convert it to a matrix and show only the first few rows and columns.
d_gow_dist <- d_gow$to_dist()
d_gow_mat <- as.matrix(d_gow_dist)
d_gow_mat[1:5, 1:5] |>
round(digits = 2) 1 2 3 4 5
1 0.00 0.21 0.25 0.24 0.07
2 0.21 0.00 0.07 0.09 0.25
3 0.25 0.07 0.00 0.06 0.26
4 0.24 0.09 0.06 0.00 0.23
5 0.07 0.25 0.26 0.23 0.00
The "gower" preset gives the same dissimilarities as cluster::daisy() with metric = "gower".
d_daisy <- cluster::daisy(
penguins_small |> dplyr::select(-species),
metric = "gower"
)
all.equal(
as.matrix(d_gow$to_dist()),
as.matrix(d_daisy),
tolerance = 1e-10
)[1] TRUE
The preset argument provides shortcuts for common distance specifications. Some presets are classical mixed-type distances, while others are designed to construct unbiased or association-aware dissimilarities.
| preset | description |
|---|---|
| gower | Gower-type mixed-data dissimilarity. |
| euclidean | Euclidean distance after one-hot encoding categorical variables. |
| u_indep | Unbiased distance with independent variable-wise contributions. |
| u_dep | Unbiased association-aware distance. |
| u_mix | Mixed unbiased association-aware distance. |
| hl | Heterogeneous Euclidean-type distance. |
| gudmm | Generalized distance for mixed data. |
| dkss | Distance for mixed data based on distributional comparisons. |
| mod_gower | Modified Gower-type dissimilarity. |
For the complete list of supported specifications and their argument combinations, see:
?mdist4 Custom specification
Presets are convenient, but users can also define custom specifications.
In a custom specification, method_cat controls the categorical dissimilarity and method_num controls the preprocessing applied to numerical variables.
d_custom <- mdist(
penguins_small |> dplyr::select(-species),
preset = "custom",
method_cat = "matching",
method_num = "std",
commensurable = TRUE
)
d_customMDist object
preset : custom
number of observations : 333
number of continuous variables : 4
number of categorical variables : 2
parameters:
- categorical method: matching
- numerical preprocessing: std
- commensurability adjustment: TRUE
- number of principal components: 6
- inertia threshold: NULL
Here, categorical variables are compared using matching dissimilarities, numerical variables are standardized, and variable-wise contributions are made commensurable. Note that pairwise distances are always computed via Manhattan distance, with the exection of euclidean and hl presets.
5 Response-aware specifications
Some distance specifications can use a response variable when constructing the dissimilarity. In these cases, the response is supplied through the response argument of mdist().
The response is not treated as an ordinary predictor. Instead, it is removed from the predictor set and used only by the components that support response-aware construction.
Response-aware construction is available in two ways:
- through response-aware presets;
- through response-aware categorical methods in custom specifications.
The response-aware presets can be inspected with all_dist_method_specs(mode = "response_aware_only").
response_aware_presets <- all_dist_method_specs(mode = "response_aware_only") |>
dplyr::filter(spec_type == "preset") |>
dplyr::distinct(preset) |>
dplyr::arrange(preset)
response_aware_presets |>
kableExtra::kbl(
format = "html",
col.names = "Response-aware preset"
) |>
kableExtra::kable_styling(full_width = FALSE)| Response-aware preset |
|---|
| u_dep |
| u_mix |
For example, the "u_dep" preset can use the response when constructing the dissimilarity.
d_response <- mdist(
penguins_small,
response = species,
preset = "u_dep"
)
d_responseMDist object
preset : u_dep
number of observations : 333
number of continuous variables : 4
number of categorical variables : 2
parameters:
- categorical method: tvd
- numerical preprocessing: pc_scores
- commensurability adjustment: TRUE
The response can also be supplied as a character string.
d_response_chr <- mdist(
penguins_small,
response = "species",
preset = "u_dep"
)
d_response_chrMDist object
preset : u_dep
number of observations : 333
number of continuous variables : 4
number of categorical variables : 2
parameters:
- categorical method: tvd
- numerical preprocessing: pc_scores
- commensurability adjustment: TRUE
In both calls, species is used as the response variable and is not included among the predictors.
The recipe interface provides the same behavior without repeating the outcome name in step_mdist(). When a recipe contains exactly one outcome, response-aware specifications automatically use the analysis-set outcomes during prep(). The fitted response-aware profiles are then reused when assessment or test observations are baked, without using their outcomes. Set response_used = FALSE in step_mdist() to request a predictor-only distance.
Response-aware construction can also be used in custom specifications. In this case, preset = "custom" is combined with a response-aware categorical method.
The following table lists the response-aware categorical methods implemented directly in manydist.
dist_methods_tbl() |>
dplyr::filter(
argument == "method_cat",
response_aware,
engine == "manydist") |>
dplyr::select(method) |>
kableExtra::kbl(full_width = FALSE)| method |
|---|
| gifi_chi2 |
| le_and_ho |
| tvd |
In addition to the methods implemented directly in manydist, categorical dissimilarities available through philentropy can also be used in response-aware custom specifications.