calc KL divergence from 2 character vectors which have distribution expression (A:B:C:...)
Source:R/distance.R
calc_KL.RdBoth `x` and `y` are parsed to numeric vectors and normalized to sum to 1 (a true probability distribution) before being handed to `philentropy::KL()`. Earlier this normalized by dividing by the *maximum* element instead of the *sum*, which does not produce a distribution that sums to 1 – the KL divergence formula is only guaranteed non-negative, and only 0 for identical inputs, when both inputs are genuine probability distributions. With the max-based normalization it could (and did) return negative values, e.g. `calc_KL("1:1:10", "1:1:1")` used to return approximately -0.664 (see phase 6 investigation); with sum-based normalization the KL divergence is always >= 0, and is exactly 0 when `x` and `y` describe the same distribution.
Arguments
- x
vector
- y
vector
- split
separator between the elements of the distribution string (default: ":"). Treated as a **literal string**, never as a regular expression, so metacharacters such as `"|"`, `"."` or `"$"` are safe. Must be a single non-empty string.
- epsilon
substituted by `philentropy::KL()` for a zero denominator so the divergence stays finite (default 1e-05, philentropy's own default); pass 0 to allow the mathematically exact `Inf`. Note philentropy applies this guard whether or not the caller asks, so it is passed explicitly rather than left implicit.
Value
numeric scalar >= 0, the KL divergence between the sum-normalized distributions parsed from `x` and `y`; 0 when `x` and `y` describe the same distribution.
Details
Zero elements: if some but not all elements of a (sum-normalized) distribution are exactly 0, a literal KL divergence formula would involve `log(0)`. `philentropy::KL()` avoids this itself: by default it substitutes a small `epsilon` (1e-05) for zero entries before taking logs, so a distribution with some zero elements still yields a finite (rather than `NaN`/`Inf`) result; this function relies on that built-in behavior rather than re-implementing its own epsilon handling. The degenerate case where *every* element of `x` or `y` is 0 (sum is 0, so the `/ sum(...)` normalization itself is 0/0) is rejected with an explicit error instead of silently producing `NaN`, consistent with how `parse_dist_values()` already refuses other degenerate inputs elsewhere in this file.
`philentropy::KL()` also prints an informational message ("Metric: 'kullback-leibler' with unit: 'log2'; ...") to the console on every call. Since this is an internal helper (not part of the public API), that message is suppressed here so it cannot leak into a caller's console output.
`x` and `y` must describe the same support (same number of elements). Previously a length mismatch was passed straight to `rbind()`, which silently recycled the shorter vector and so compared the wrong outcomes against each other. Negative inputs are rejected for the same reason: they cannot be normalised into a probability distribution. To compare distributions of differing length, use `distribution_distance()`.