Skip to contents

Two 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"`.

Value

An object of class `eiod_check`.

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.