Every cut-off in Tables 3 and 4a-4g of the Intake methods paper, in long format: one row per metric, indicator, demographic group and table row.
Format
A data frame with 616 rows and 15 columns:
- metric
`"abs"` for Table 3, `"rel"` for Tables 4a-4g
- table
Source table: `"3"`, `"4a"` ... `"4g"`
- indicator
Short indicator name used by the `eiod_*` functions
- indicator_label
Human-readable indicator name
- unit
Unit **this table is printed in**, per capita per day. The same for both tables for six indicators; for eutrophication, kg for Table 3 and g for Table 4f
- demogroup
Demographic group, 1-8
- demogroup_label
Group name, e.g. "Male 10+ yr"
- sex
Factor, `"male"` or `"female"`
- age_min, age_max
Age bounds in years; 999 means no upper bound
- row_order
Position in the source table
- percentile
10-90 for relative rows 1-9; `NA` for absolute rows and for row 10, which repeats P90 as a lower bound
- value
**The cut-off the metric functions compare against.** Nothing is rescaled: for 608 rows this is exactly what the paper prints, and for the other eight it is exactly what Intake supplied
- value_published_str
The same value as a character string, exactly as received. Shipped so the figure can be compared character for character, not as a rendering of a double
- value_source
`"published"` for the 608 rows transcribed from the paper; `"intake correction 2026-10"` for the eight Table 3 eutrophication thresholds Intake corrected. **Those eight do not match the currently published PDF** - see the section above
Source
Intake-EIOD-Methods-Paper-Jan2026-Final.pdf, Tables 3 and 4a-4g (pages 16-19), available at <https://www.intake.org/sites/default/files/2026-01/Intake-EIOD-Methods-Paper-Jan2026-Final.pdf>. Transcribed programmatically; see `data-raw/build_data.R`. The same source file drives a companion Stata implementation.
Details
Tables 5a and 5b are deliberately **not** stored here. They are composites that reuse values already present - the HESD criterion is `metric == "abs" & indicator == "biodiv"`, and the HDLEI criterion is `metric == "rel" & indicator == "biodiv" & percentile == 30`. A second copy could drift from the first.
Nothing here is rescaled
**`value` is the cut-off exactly as this package received it, for all 616 rows**, and `value_published_str` is the same number as literal text. The package applies no conversion to a cut-off and none to your data.
For 608 rows "as received" means "as printed in the methods paper", and you can check them against the PDF character for character. The remaining eight are described in the next section.
Eight rows differ from the published PDF, on Intake's instruction
The **Table 3 eutrophication thresholds** in `eiod_cutoffs` are **not** the numbers the currently published paper prints. They are corrections supplied by Intake in October 2026, and the `value_source` column marks them:
“`r subset(eiod_cutoffs, value_source != "published", c(demogroup_label, unit, value, value_source)) “`
**What was wrong.** The paper prints those eight cells in **kilograms** PO4(3-)eq while Table 4f, and the EIOF food databases, use **grams**. Intake confirmed by email that both tables are intended to be in grams, and supplied the corrected Table 3 values.
**What changed, and what did not.** The corrected values are the printed ones multiplied by 1000, carried to full precision - the quantity is identical, only the unit it is expressed in has changed. Dividing any corrected value by 1000 reproduces the printed figure to the ten decimals the PDF gives, and `data-raw/build_data.R` asserts exactly that. **No classification moves**: tested on 400,000 simulated gram-scale values, old and new behaviour agreed everywhere except within about one unit in the last place of a cut-off, where the new path is the more exact of the two because it no longer divides before comparing.
**Consequence for you: supply eutrophication in grams**, which is what the EIOF databases give you (`Eutr. (g PO43-e/kg)` x kg food = g). Every indicator now uses one unit across both tables, and nothing is converted anywhere. Between July and October 2026 this package divided eutrophication values by 1000 on your behalf; that step is gone.
See `vignette("eutrophication")` for the full history, including the evidence that led to the question being raised.
Checking a value against the printed table
Two columns carry the same number in two forms, so that a reader can check the package without having to trust any numeric rendering:
| `value_published_str` | the literal characters from the paper, never through a numeric type |
| `value` | the nearest IEEE 754 double to that text - and what the metric functions compare against |
`data-raw/build_data.R` asserts that `as.numeric(value_published_str) == value` for all 616 rows, and that each parsed value still prints back to exactly its published digits.
A `double` cannot hold most decimal fractions exactly - that is true of every statistical package, not of this one. What is guaranteed here is that the stored double is the nearest double to the published decimal, that it round-trips back to that decimal, and that the decimal itself is in the file as text. **If you need an exact decimal comparison, compare against `value_published_str`.**
Note that R's default `options(digits = 7)` will not show you a published value in full: 15 of the 616 need 14 significant digits. [eiod_lookup_cutoff()] prints at full precision for this reason.
Examples
data(eiod_cutoffs)
str(eiod_cutoffs)
#> 'data.frame': 616 obs. of 15 variables:
#> $ metric : chr "abs" "abs" "abs" "abs" ...
#> $ table : chr "3" "3" "3" "3" ...
#> $ indicator : chr "biodiv" "biodiv" "biodiv" "biodiv" ...
#> $ indicator_label : chr "Biodiversity loss" "Biodiversity loss" "Biodiversity loss" "Biodiversity loss" ...
#> $ unit : chr "PDF*year" "PDF*year" "PDF*year" "PDF*year" ...
#> $ demogroup : int 1 2 3 4 5 6 7 8 1 2 ...
#> $ demogroup_label : chr "Male 0-1.9 yr" "Male 2-4.9 yr" "Male 5-9.9 yr" "Male 10+ yr" ...
#> $ sex : Factor w/ 2 levels "male","female": 1 1 1 1 2 2 2 2 1 1 ...
#> $ age_min : num 0 2 5 10 0 2 5 10 0 2 ...
#> $ age_max : num 1.9 4.9 9.9 999 1.9 4.9 9.9 999 1.9 4.9 ...
#> $ row_order : int 7 7 7 7 7 7 7 7 5 5 ...
#> $ percentile : int NA NA NA NA NA NA NA NA NA NA ...
#> $ value : num 3.69e-13 5.72e-13 7.88e-13 1.28e-12 3.57e-13 ...
#> $ value_published_str: chr "3.6896027444E-13" "5.7244838747E-13" "7.8836516181E-13" "1.2844358718E-12" ...
#> $ value_source : chr "published" "published" "published" "published" ...
# the HESD biodiversity criterion
subset(eiod_cutoffs, metric == "abs" & indicator == "biodiv",
c(demogroup_label, value))
#> demogroup_label value
#> 1 Male 0-1.9 yr 3.689603e-13
#> 2 Male 2-4.9 yr 5.724484e-13
#> 3 Male 5-9.9 yr 7.883652e-13
#> 4 Male 10+ yr 1.284436e-12
#> 5 Female 0-1.9 yr 3.574921e-13
#> 6 Female 2-4.9 yr 5.301871e-13
#> 7 Female 5-9.9 yr 7.238206e-13
#> 8 Female 10+ yr 1.033173e-12