UNE-EN 689: Quantitative Statistical Exposure Assessment

Overview

UNE-EN 689 is a European standard that defines a two-stage statistical procedure for comparing measured occupational exposure levels against occupational exposure limits (OELs). It is designed to provide a statistically rigorous and reproducible conformity decision based on a representative set of exposure measurements collected over multiple working days.

The standard assumes that daily exposure (ED) values follow a lognormal or normal distribution and uses a one-sided upper tolerance limit (LSC_{95,70}) to decide, with 95% confidence and 70% coverage, whether exposure is below the OEL.

The two-stage procedure

Stage 1: Preliminary assessment (minimum 3 measurement days)

Each measurement day produces one or more samples. The daily exposure ED is calculated as the time-weighted average over an 8-hour shift. The exposure index IE = ED / OEL is then computed for each day.

Decision rules:

Condition Outcome
All IE < 0.1 CONFORMITY — exposure is well below the OEL
Any IE > 1 NON-CONFORMITY — at least one day exceeds the OEL
Any IE between 0.1 and 1 NO DECISION — proceed to Stage 2

Stage 2: Statistical assessment (minimum 6 measurement days total)

The full set of ED values (preliminary + additional days) is fitted to a lognormal or normal distribution using the Shapiro-Wilk test. The one-sided upper tolerance limit LSC_{95,70} is then compared against the OEL via the risk index UR. If UR ≥ UT (tabulated tolerance factor), conformity is declared.

Stage 1 example

# Five samples across three working days
data <- data.frame(
  day           = c(1, 1, 2, 3, 3),
  concentration = c(12, 8, 9, 5, 6),   # mg/m³
  time          = c(4,  4, 8, 3, 5)    # hours
)

res_pre <- une689_evaluate_preliminary(data, vla = 10)
res_pre$days_table
#>   day     ED     IE
#> 1   1 10.000 1.0000
#> 2   2  9.000 0.9000
#> 3   3  5.625 0.5625
res_pre$result
#> [1] "NO DECISION"

Step-by-step

# Daily exposure for day 1 (two samples)
une689_daily_exposure(concentration = c(12, 8), time = c(4, 4))
#> [1] 10

# Exposure index
une689_exposure_index(ed = 10, vla = 10)
#> [1] 1

# Classify conformity from a set of IE values
une689_classify_conformity(c(1.0, 0.9, 0.5625))
#> [1] "NO DECISION"

Stage 2 example

When the preliminary assessment returns NO DECISION, additional measurement days are collected and the full statistical assessment is performed on the combined dataset.

# Six ED values (3 preliminary + 3 additional)
eds <- c(10, 9, 5.625, 11, 8, 13)

res_est <- une689_evaluate_statistical(eds, vla = 10)

cat("Distribution:", res_est$distribution_type, "\n")
#> Distribution: Lognormal
cat("MG =",  round(res_est$MG,  3), "\n")
#> MG = 9.13
cat("DSG =", round(res_est$DSG, 3), "\n")
#> DSG = 1.336
cat("UT =",  res_est$ut, "\n")
#> UT = 2.187
cat("LSC(95,70) =", round(res_est$lsc, 3), "\n")
#> LSC(95,70) = 17.21
cat("UR =",  round(res_est$ur, 3), "\n")
#> UR = 0.314
cat("Result:", res_est$conformity, "\n")
#> Result: NON-CONFORMITY

Step-by-step

# Descriptive statistics
est <- une689_statistics(eds)
est$MG; est$DSG
#> [1] 9.129882
#> [1] 1.33626

# Normality and lognormality tests
test <- une689_normality_test(eds)
test$pval_lognormal
#> [1] 0.8702792

# Distribution type (lognormal has priority)
distribution_type <- une689_distribution_type(
  pval_normal    = test$pval_normal,
  pval_lognormal = test$pval_lognormal
)
distribution_type
#> [1] "Lognormal"

# Tolerance factor UT for n = 6
une689_ut(6)
#> [1] 2.187

# LSC(95,70)
une689_lsc(distribution_type, ut = une689_ut(6), MG = est$MG, DSG = est$DSG)
#> [1] 17.2103

# Risk index UR
une689_ur(distribution_type, vla = 10, MG = est$MG, DSG = est$DSG)
#> [1] 0.3140406

# Conformity decision
une689_statistical_conformity(ur = une689_ur(distribution_type, vla = 10,
                                               MG = est$MG, DSG = est$DSG),
                                ut = une689_ut(6))
#> [1] "NON-CONFORMITY"

Periodic assessment (monitoring interval)

Once conformity has been established, the standard requires defining how frequently measurements should be repeated. Two options are available:

# Option 1: MG or MA versus the OEL
une689_monitoring_interval_opt1(reference_value = res_est$MG, vla = 10)
#> [1] "Recommended monitoring interval: 12 months"

# Option 2: LSC(95,70) versus the OEL
une689_monitoring_interval_opt2(lsc = res_est$lsc, vla = 10)
#> [1] "Not recommended. Exposure must be reviewed."

Additive effects

When workers are simultaneously exposed to multiple agents affecting the same target organ, the European standard requires that the combined exposure index be evaluated:

IE_combined = IE_agent1 + IE_agent2 + ... + IE_agentN

Conformity requires IE_combined ≤ 1. For example, if toluene (IE = 0.20) and xylene (IE = 0.30) both affect the central nervous system:

ie_toluene <- 0.20
ie_xylene  <- 0.30
ie_combined <- ie_toluene + ie_xylene

cat("Combined IE:", ie_combined, "\n")
#> Combined IE: 0.5
une689_classify_conformity(ie_combined)
#> [1] "NO DECISION"

Agents can appear in more than one additive group if they affect multiple target organs. The une689_from_excel() function and the Shiny application handle multiple independent additive groups automatically.

From Excel (no coding required)

The UNE-EN 689 Excel template has three sheets:

ruta <- system.file("plantillas", "plantilla_une689.xlsx", package = "expoquimR")
res <- une689_from_excel(ruta)

# Preliminary results and statistical assessment per agent
res$preliminary$Toluene$result
res$preliminary$Toluene$statistics$conformity

# Additive effects table
res$additive

Language

expoquimr_lang("es")
une689_classify_conformity(c(0.02, 0.05))
#> [1] "CONFORMIDAD"
une689_distribution_type(0.5, 0.5)
#> [1] "Lognormal"
une689_monitoring_interval_opt1(0.5, vla = 10)
#> [1] "Periodicidad recomendada: 36 meses"
expoquimr_lang("en")

Interactive application

run_une689()

The UNE-EN 689 Shiny application supports:

Methodological note

A known implementation error in some versions of this standard involves the use of all(IE < 0.1, na.rm = TRUE) to test conformity. In R, all() on an empty vector returns TRUE, which would incorrectly declare conformity when no valid IE values are available. expoquimR corrects this by returning NA from une689_classify_conformity() when the input contains no valid IE values.

References