The question: where does this diet sit in a fixed global reference distribution?
The cut-points are Tables 4a–4g of the methods paper — nine decile boundaries per indicator per demographic group, 560 numbers in all. The result is a band from 1 (lowest impact) to 10.
This article assumes you have run
vignette("data-checks") and have a grp vector
from vignette("demographic-groups"):
grp <- eiod_age_sex_group(eiod_demo$age, eiod_demo$sex)Part 1 — Using it
A. One value
# a 40-year-old man, 9e-13 PDF*year of biodiversity loss — group 4
eiod_relative_band(9e-13, group = 4, indicator = "biodiv")
#> [1] 5The decile boundaries it was placed between:
eiod_relative_band(9e-13, 4, "biodiv", details = TRUE)
#> value group band cut_lower cut_upper
#> 1 9e-13 4 5 8.967337e-13 9.039909e-13B. One vector (a column from your data)
band <- eiod_relative_band(eiod_demo$biodiv_pdf, grp, "biodiv")
table(band, useNA = "ifany")
#> band
#> 1 2 3 4 5 6 7 8 9 10 <NA>
#> 212 3 27 19 1 67 44 99 64 52 12
head(eiod_relative_band(eiod_demo$biodiv_pdf, grp, "biodiv", details = TRUE), 4)
#> value group band cut_lower cut_upper
#> 1 1.670692e-12 4 8 1.537477e-12 2.494486e-12
#> 2 5.547457e-13 4 1 NA 7.041503e-13
#> 3 9.416969e-13 4 6 9.039909e-13 1.224707e-12
#> 4 2.538843e-13 4 1 NA 7.041503e-13cut_lower is NA in band 1 and
cut_upper is NA in band 10 — correctly,
because nothing is published below P10 or above P90.
C. Adding the result as a new column
d <- eiod_demo
d$group <- eiod_age_sex_group(d$age, d$sex)
d$band_biodiv <- eiod_relative_band(d$biodiv_pdf, d$group, "biodiv")
d$band_water <- eiod_relative_band(d$water_litres, d$group, "water")
head(d[, c("id", "group", "biodiv_pdf", "band_biodiv", "band_water")], 5)
#> id group biodiv_pdf band_biodiv band_water
#> 1 1 4 1.670692e-12 8 1
#> 2 2 4 5.547457e-13 1 1
#> 3 3 4 9.416969e-13 6 1
#> 4 4 4 2.538843e-13 1 1
#> 5 5 8 6.225413e-12 10 1D. Several indicators in one call
bands <- eiod_relative_all(eiod_demo, grp, eiod_demo_map)
round(vapply(bands, mean, numeric(1), na.rm = TRUE), 2)
#> band_landtotal band_landarable band_landpasture band_ghg
#> 4.68 3.00 5.10 3.81
#> band_eutroph band_water band_biodiv
#> 4.85 3.39 5.06E. Only the indicators you have
Supply any subset — the same named-vector mapping as everywhere else, and nothing is computed for indicators you leave out:
two <- c(landtotal = "land_total_m2yr", water = "water_litres")
res <- eiod_relative_all(eiod_demo, grp, map = two)
str(res)
#> 'data.frame': 600 obs. of 2 variables:
#> $ band_landtotal: int 4 3 4 4 1 1 5 1 4 1 ...
#> $ band_water : int 1 1 1 1 1 3 3 1 4 1 ...
round(vapply(res, mean, numeric(1), na.rm = TRUE), 2)
#> band_landtotal band_water
#> 4.68 3.39Identical to calling the single-indicator form:
identical(res$band_water,
eiod_relative_band(eiod_demo$water_litres, grp, "water"))
#> [1] TRUEBinding a subset onto your data frame, and the midpoint form in the same call:
d3 <- cbind(eiod_demo,
eiod_relative_all(eiod_demo, grp, map = two,
midpoint = TRUE, prefix = "mid_"))
head(d3[, c("id", "mid_landtotal", "mid_water")], 4)
#> id mid_landtotal mid_water
#> 1 1 35 5
#> 2 2 25 5
#> 3 3 35 5
#> 4 4 35 5Part 2 — What the bands actually mean
The relative benchmark metrics are the part of the Intake framework most often misread, and the misreading changes what the numbers mean. The rest of this article is about that one idea.
The reference distribution is external and fixed
eiod_relative_band() does not rank
respondents against each other in your survey. Each one-day diet is
compared against a reference distribution that is the same for every
analysis anywhere in the world.
Intake built it in three steps:
- For each country, average dietary environmental impact per person per day at each decile, from the Planet-Based Diets Database (WWF, 2020).
- Those country values population-weighted, using 2010 country populations, to give a global percentile distribution of impacts per person per day.
- The resulting all-population decile values scaled to each demographic group by its share of average energy requirements.
The result is a fixed table of numbers, printed in the paper and shipped in this package:
subset(eiod_cutoffs,
metric == "rel" & indicator == "biodiv" & demogroup == 4 &
!is.na(percentile),
select = c(percentile, value))
#> percentile value
#> 87 10 7.041503e-13
#> 88 20 7.156354e-13
#> 89 30 8.436509e-13
#> 90 40 8.967337e-13
#> 91 50 9.039909e-13
#> 92 60 1.224707e-12
#> 93 70 1.537477e-12
#> 94 80 2.494486e-12
#> 95 90 3.640560e-12Your data never changes those numbers.
Why quantile() is the wrong tool
This is the practical consequence. If you compute deciles from your own sample, you get roughly 10% of observations in each band by construction:
# WRONG: ranks the sample against itself
wrong <- cut(eiod_demo$biodiv_pdf,
breaks = quantile(eiod_demo$biodiv_pdf, seq(0, 1, 0.1),
na.rm = TRUE),
labels = 1:10, include.lowest = TRUE)
table(wrong)
#> wrong
#> 1 2 3 4 5 6 7 8 9 10
#> 59 59 59 58 59 59 58 59 59 59
# RIGHT: compares against the published global reference
right <- eiod_relative_band(eiod_demo$biodiv_pdf, grp, "biodiv")
table(right)
#> right
#> 1 2 3 4 5 6 7 8 9 10
#> 212 3 27 19 1 67 44 99 64 52The first is flat because it has to be. The second is not, and that shape is the information: it tells you where this population sits relative to global dietary patterns. The first tells you only that some of your respondents have higher impacts than others, which you already knew.
If your whole sample has unusually low impacts, your whole sample lands in low bands. That is the intended behaviour, and is exactly why the metric is comparable across countries and over time.
How the bands are defined
Each table gives ten rows. Rows 1–9 carry the P10…P90 cut-points; row 10 repeats the P90 value as a lower bound.
| Band | Condition |
|---|---|
| 1 | impact < P10 |
| 2 | P10 ≤ impact < P20 |
| … | … |
| 9 | P80 ≤ impact < P90 |
| 10 | impact ≥ P90 |
The inequality is strict, so a diet sitting exactly on P10 belongs in band 2:
p10 <- unname(eiod_lookup_cutoff("biodiv", 4, "rel", percentile = 10))
eiod_relative_band(c(p10 * (1 - 1e-9), p10), c(4L, 4L), "biodiv")
#> [1] 1 2Reporting
The paper gives two forms. The first is the distribution:
“x% of one-day diets fall between the 10th and 20th percentile of global per capita dietary total land use.”
round(100 * prop.table(table(eiod_relative_band(eiod_demo$land_total_m2yr, grp,
"landtotal"))), 1)
#>
#> 1 2 3 4 5 6 7 8 9 10
#> 14.8 0.3 19.2 23.7 15.8 0.2 2.7 14.5 2.5 6.3The second is a mean position, for which midpoint = TRUE
gives band midpoints (5, 15, … 95):
mid <- eiod_relative_band(eiod_demo$land_total_m2yr, grp, "landtotal",
midpoint = TRUE)
mean(mid, na.rm = TRUE)
#> [1] 41.83333A caution on that mean
Averaging a band index treats the bands as equally spaced on the impact scale. They are emphatically not:
p <- vapply(seq(10, 90, 10),
function(q) unname(eiod_lookup_cutoff("landpasture", 4, "rel", q)),
numeric(1))
round(diff(p), 3)
#> [1] 0.006 2.225 2.721 4.845 0.152 0.594 12.788 5.365In pasture land use the P10–P20 gap is a fraction of a square metre-year while the P80–P90 gap is several. A mean band is a legitimate summary of position in the reference distribution. It is not a summary of impact. If you want a mean impact, average the impact variable itself.
The limitation the paper states about itself
The reference distribution is built from Food Balance Sheet data — national availability averages, not individual consumption. It therefore captures variation between countries, not variation between people or between days.
The authors’ argument is reasonable: for assessment, monitoring and cross-country comparison, this matters less so long as the reference distribution stays fixed, because it still provides a consistent yardstick. But it does mean a band is a statement about where a diet sits relative to national average availability patterns, not relative to other individuals. That distinction belongs in the methods section of anything you publish using these.
And the thing worth repeating
A low band is not evidence of sustainability. The reference distribution describes diets as they are, and most of them exceed the planetary boundaries. For greenhouse gas emissions, every band — including band 1 — lies above the Table 3 absolute threshold:
thr <- unname(eiod_lookup_cutoff("ghg", 4, "abs"))
p10 <- unname(eiod_lookup_cutoff("ghg", 4, "rel", percentile = 10))
c(absolute_threshold = thr, reference_P10 = p10, threshold_is_lower = thr < p10)
#> absolute_threshold reference_P10 threshold_is_lower
#> 2.142928 3.105870 1.000000So “this population is in the lowest decile globally for dietary greenhouse gas emissions” and “this population’s diets are within the planetary boundary” can both be false at the same time, or the first true and the second false. Report the absolute and relative metrics side by side.
Where each absolute threshold falls inside its own reference distribution, for all seven indicators:
for (ind in eiod_indicators$indicator) {
thr <- unname(eiod_lookup_cutoff(ind, 4, "abs"))
p <- vapply(seq(10, 90, 10),
function(q) unname(eiod_lookup_cutoff(ind, 4, "rel", q)),
numeric(1))
k <- sum(thr >= p)
pos <- if (k == 0) "below P10" else if (k == 9) "at/above P90" else
sprintf("P%d-P%d", k * 10, (k + 1) * 10)
cat(sprintf("%-12s %s\n", ind, pos))
}
#> landtotal P40-P50
#> landarable P60-P70
#> landpasture P40-P50
#> ghg below P10
#> eutroph P40-P50
#> water at/above P90
#> biodiv P60-P70Greenhouse gases sit below P10 — a diet in the lowest band still exceeds the boundary. Water sits above P90, so essentially every diet passes. The two metric families answer different questions and will not agree.
See also
-
vignette("table3-absolute")— Table 3, the absolute thresholds -
vignette("table5-composites")— Tables 5a and 5b -
?eiod_relative_band,?eiod_relative_all,?eiod_lookup_cutoff