Check the numerical precision of an impact variable
Source:R/check_impact.R
eiod_check_precision.RdTwo related checks: how many significant digits the stored values actually retain, and how many observations sit close enough to their own cut-off that the classification could flip under rounding.
Usage
eiod_check_precision(
value,
group = NULL,
indicator = NULL,
name = "impact",
tolerance = 1e-06,
metric = c("abs", "rel"),
percentile = NULL
)Arguments
- value
Numeric vector of impact values.
- group
Optional demographic groups 1-8. Required for the cut-off proximity check.
- indicator
Optional indicator name. Required for the proximity check.
- name
A label for the variable, used in the report.
- tolerance
Relative distance from a cut-off below which a classification is treated as not robust. Default `1e-6`.
- metric
Which cut-off to measure distance from: `"abs"` (default) or `"rel"`.
- percentile
Required when `metric = "rel"`.
The small exponent is not the problem
R's `numeric` is an IEEE 754 double: around 15 to 17 significant decimal digits, with an exponent range to about 1e+/-308. A biodiversity value of `3.6896e-13` is comfortably representable, and comparison with `<` is exact. No epsilon is needed, provided both sides carry full precision.
The real risk is **ingestion fidelity** - digits lost before R ever sees the number. Excel displays `3.69E-13` and can write back only what it displays; CSV exports written with a ` `float` storage holds about 7 significant digits; database `REAL` columns are single precision for the same reason.
What the checks measure
The first finds, for each distinct value, the smallest number of significant digits that reproduces it exactly. Across many distinct values, a maximum of 7 or fewer is consistent with single-precision storage or a truncated export. Measured on simulated data, full-precision values return 17, a single-precision round trip returns exactly 7, and an Excel three-digit re-save returns 3, so the cases separate cleanly.
The second is the one that answers whether precision matters *here*. It computes, for each observation, the relative distance to the cut-off that applies to it, and counts those within `tolerance`. Usually the answer is zero and the worry can be set aside; when it is not, you get the row numbers.
Nothing is repaired. Digits that were never read cannot be recovered.
Examples
data(eiod_demo)
grp <- eiod_age_sex_group(eiod_demo$age, eiod_demo$sex)
eiod_check_precision(eiod_demo$biodiv_pdf, grp, "biodiv",
name = "biodiv_pdf")
#> reiod data quality report
#>
#> ERROR 0
#> WARNING 0
#> NOTE 2
#>
#> NOTE biodiv_pdf precision up to 17 significant digits retained across 588 distinct values.
#> NOTE biodiv_pdf proximity no observation sits within 1e-06 of the absolute threshold, so stored
#> precision does not change any classification here.
#>
#> No blocking problems.
# the same values after a single-precision round trip
eiod_check_precision(signif(eiod_demo$biodiv_pdf, 7), grp, "biodiv",
name = "biodiv_float")
#> reiod data quality report
#>
#> ERROR 0
#> WARNING 1
#> NOTE 1
#>
#> WARNING biodiv_float precision at most 7 significant digits across 588 distinct values. Consistent with
#> single-precision storage or a truncated export. Check how the column was
#> written.
#> NOTE biodiv_float proximity no observation sits within 1e-06 of the absolute threshold, so stored
#> precision does not change any classification here.
#>
#> No blocking problems.