Package {essential8}


Title: Reproducible Cardiovascular Health Metric Scoring
Version: 0.9.0
Description: Provides a reproducible R implementation of the American Heart Association Life's Essential 8 cardiovascular health scoring framework for adults aged 20 years or older and children aged 4 months to 19 years. Calculates the eight component scores and their unweighted composite score from available component data, including raw MEPA, DASH, and HEI-2015 diet inputs and pediatric growth-chart and blood-pressure percentiles, using the 2022 definitions described by Lloyd-Jones et al. (2022) <doi:10.1161/CIR.0000000000001078>.
License: MIT + file LICENSE
Depends: R (≥ 4.1.0)
Encoding: UTF-8
Language: en-US
Imports: cli (≥ 3.6.0), generics, rlang (≥ 1.1.0)
Suggests: cdcanthro, dplyr (≥ 1.1.0), ggforestplotR (≥ 0.6.0), ggplot2 (≥ 3.4.0), knitr, mice (≥ 3.16.0), pedbp, rmarkdown, testthat (≥ 3.0.0), tibble
VignetteBuilder: knitr
Config/testthat/edition: 3
Config/Needs/website: pkgdown
Config/Needs/build: digest, haven, survey
URL: https://thatoneguy006.github.io/essential8/, https://github.com/thatoneguy006/essential8
BugReports: https://github.com/thatoneguy006/essential8/issues
Config/roxygen2/version: 8.1.1
NeedsCompilation: no
Packaged: 2026-11-14 20:56:20 UTC; Carso
Author: Carson Richardson ORCID iD [aut, cre, cph], Amrik Khalsa ORCID iD [ctb], Sara Conroy ORCID iD [ctb]
Maintainer: Carson Richardson <carson.richardson@outlook.com>
Repository: CRAN
Date/Publication: 2026-11-14 21:20:09 UTC

essential8: Reproducible cardiovascular health metric scoring

Description

essential8 is a transparent, versioned, and auditable implementation of published adult cardiovascular health metric definitions. Adult scoring, including transparent handling of unavailable components, is based on the American Heart Association's 2022 Life's Essential 8 definition and is available through score_le8().

Scientific status

The adult scoring rules in version 0.3.0 are implemented from the cited AHA, DASH, and HEI-2015 sources and covered by boundary and input-validation tests. Users remain responsible for verifying measurement protocols, population-specific diet cutpoints or percentiles, and caller-adjudicated clinical-judgment flags. The package is research software and is not intended for clinical decision support.

Author(s)

Maintainer: Carson Richardson carson.richardson@outlook.com (ORCID) [copyright holder]

Authors:

Other contributors:

See Also

Useful links:


Add pediatric growth-chart and blood-pressure reference values

Description

Derives the reference inputs that score_le8() needs for pediatric BMI and blood-pressure scoring from raw measurements:

Requires the suggested packages cdcanthro (for growth charts) and pedbp (for blood pressure); each is needed only when data contains rows of the corresponding ages. Values are left missing outside the stated ages and wherever a required measurement is missing. In particular, the blood-pressure references are not computed without height: pedbp would otherwise assume a median-height child.

infant_weight_z_change, the change in the infant z-score since the prior routine visit, needs longitudinal data and is not derived here. Compute it from infant_weight_z within each child; see vignette("pediatric-scoring").

Usage

add_pediatric_references(
  data,
  sex = "sex",
  height = "height_cm",
  weight = "weight_kg",
  bmi = NULL,
  age_months = NULL,
  completed_months = FALSE,
  infant_measure = c("weight_for_length", "bmi_for_age"),
  bp_source = "flynn2017"
)

Arguments

data

A data frame. Rows aged 20 or older are returned unchanged.

sex

Name of the sex column: "m"/"f", "male"/"female", or 0/1 (0 = male), or a logical column named female.

height

Name of the column holding height in cm (recumbent length before age 2).

weight

Name of the column holding weight in kg.

bmi

Optional name of a BMI column in kg/m^2. When NULL (the default), BMI is calculated from weight and height.

age_months

Optional name of a column holding age in months. When NULL, age_months is used if present, otherwise age * 12.

completed_months

If FALSE (the default), ages are exact, so 54 months means exactly 4.5 years. If TRUE, ages are completed months (as in NHANES) and 0.5 is added before every reference lookup. Unlike calling cdcanthro directly, whose midpoint adjustment depends on whether every age in the batch is a whole number, the result for one row never depends on the other rows.

infant_measure

Under age 2, "weight_for_length" (the default, the more common clinical measure) or "bmi_for_age"; AHA 2022 accepts either.

bp_source

The pedbp blood-pressure reference. The default, "flynn2017", is the AAP 2017 guideline that LE8 cites.

Value

data, with the eight reference columns described above appended. It is an error for data to contain any of them already.

References

Lloyd-Jones DM, Allen NB, Anderson CAM, et al. (2022). Life's Essential 8. Circulation, 146(5), e18-e43. doi:10.1161/CIR.0000000000001078

Flynn JT, Kaelber DC, Baker-Smith CM, et al. (2017). Clinical Practice Guideline for Screening and Management of High Blood Pressure in Children and Adolescents. Pediatrics, 140(3), e20171904. doi:10.1542/peds.2017-1904

Wei R, Ogden CL, Parsons VL, Freedman DS, Hales CM (2020). A method for calculating BMI z-scores and percentiles above the 95th percentile of the CDC growth charts. Annals of Human Biology, 47(6), 514-521. doi:10.1080/03014460.2020.1808065

See Also

score_le8()

Examples


children <- data.frame(
  id = c("a", "b"),
  age = c(5.5, 14),
  sex = c("female", "male"),
  height_cm = c(112, 165),
  weight_kg = c(19, 70)
)
add_pediatric_references(children)


Restore LE8 score methods to a data frame

Description

score_le8() returns an essential8_scores object: the input data frame (or tibble), with its original class, plus the score columns. The extra class provides summary(), tidy(), plot(), and, with dplyr loaded, summarise().

Row-wise operations such as filter(), mutate(), arrange(), joins, and bind_rows() keep the class. group_by(), summarise() with expressions, as_tibble(), pivot_longer(), and saving to and reading from a file drop it. as_le8_scores() adds the class back to any data frame that still contains the score columns. It does not rescore or change any values.

A data frame with an .imp column, such as saved results from score_le8_imputed(), becomes an essential8_imputed_scores object, so its methods pool across imputations again.

Usage

as_le8_scores(x)

Arguments

x

A data frame containing the columns returned by score_le8(): the eight component scores (diet_score, physical_activity_score, nicotine_score, sleep_score, bmi_score, blood_lipids_score, blood_glucose_score, and blood_pressure_score), n_components, le8_composite_score, le8_category, and le8_population.

Value

x, with the class essential8_scores added, and essential8_imputed_scores too when x has an .imp column.

See Also

score_le8()

Examples

scores <- score_le8(
  data.frame(age = 45, sleep_hours = 7.5, bmi = 24, bmi_profile = "general"),
  min_components = 2
)
plain <- as.data.frame(scores)
summary(as_le8_scores(plain))

Construct a reference for population diet scoring

Description

Creates a small, method-specific reference for DASH or HEI-2015 indices, including HEI-2015 totals calculated from raw inputs. Raw DASH with custom definitions requires explicit dash_cutpoints in score_le8() to specify intake quintiles as well. The four values are index-score cutpoints at the indicated percentiles, not percentiles themselves. No observations are stored or ranked.

Usage

diet_reference(
  p25,
  p50,
  p75,
  p95,
  method = "dash",
  label = NULL,
  source = NULL,
  score_range = NULL
)

Arguments

p25, p50, p75, p95

Single finite numeric cutpoints, in nondecreasing order.

method

Either "dash" or "hei2015", matched case-insensitively.

label, source

Optional single nonempty strings describing the reference population and its source. These do not change scoring.

score_range

Optional numeric vector of two finite bounds identifying the index's theoretical range. HEI-2015 always uses 0 to 100. DASH has multiple definitions, so a custom DASH reference has no implicit range.

Value

An essential8_diet_reference object containing the method, cutpoints, optional metadata, and index range. It identifies percentile bands, not an exact continuous percentile distribution.

Examples

ref <- diet_reference(40, 55, 65, 80, method = "hei2015",
                      label = "Synthetic example")
ref

Options for imputing missing LE8 inputs

Description

Sets how score_le8() imputes missing inputs when impute is used. Pass the result as score_le8(impute = le8_imputation_control(...)); impute = TRUE uses the defaults.

Usage

le8_imputation_control(m = 20, maxit = 5, seed = NA, auxiliary = NULL, ...)

Arguments

m

Number of imputed data sets, at least 2. A common rule of thumb for final analyses is at least as many imputations as the percentage of participants with any missing input.

maxit

Number of mice iterations.

seed

A whole number to make the imputations reproducible, or NA (the default) to use the session's random number stream.

auxiliary

Optional character vector of other complete columns to use as predictors, such as analysis outcomes, exposures, or survey design variables; see le8_imputation_setup().

...

Further arguments to mice::mice(), such as printFlag = TRUE to show mice's iteration log. Arguments with the same names as the imputation settings (for example, method or predictorMatrix) replace them.

Value

An essential8_imputation_control object.

See Also

score_le8(), le8_imputation_setup()

Examples

le8_imputation_control(m = 50, seed = 2026)

Prepare LE8 inputs for multiple imputation with mice

Description

le8_imputation_setup() returns the settings mice::mice() needs to multiply impute missing score_le8() inputs in a way the AHA scoring rules can use. score_le8(impute = TRUE) uses them to impute and score in one call; call le8_imputation_setup() yourself to inspect the settings, or to adjust them and run mice directly, then score the result with score_le8_imputed().

Imputing the inputs, rather than the 0-100 scores, keeps the relationships between measurements that the AHA bands then summarize. The setup encodes what is specific to LE8:

Two values that follow from observed data are filled in before imputation (deductive imputation): glucose_measure is "hba1c" when diabetes is TRUE, and current_inhaled_nds is FALSE for current smokers.

Usage

le8_imputation_setup(data, auxiliary = NULL, diet_method = "mepa")

Arguments

data

A data frame of score_le8() inputs.

auxiliary

Optional character vector of other columns in data to use as predictors, such as analysis outcomes, exposures, or survey design variables. They must be complete; they are not imputed.

diet_method

The diet scoring method; only "mepa" is supported.

Details

Observed values are validated with score_le8() first, so data that cannot be scored stop here rather than after imputation. Every observed glucose_value needs its glucose_measure.

Only the MEPA diet screener is supported. Inputs must use the default column names, and age must be complete.

With adults and children in one data set, inputs that apply to only one population cannot predict inputs that apply to both. To use richer models, impute each population separately and combine the results with rbind(), which mice provides for mids objects.

Imputation models should include the variables used in later analyses, such as exposures and outcomes. Pass them in auxiliary.

score_le8(impute = TRUE) calls mice::mice() with remove.collinear = FALSE and remove.constant = FALSE. mice's defaults would stop imputing an input that is constant or collinear in the observed data, leaving values that scoring needs missing. Each imputation model still drops such predictors on its own. When calling mice::mice() directly with a setup, pass the same two arguments.

Glucose values mix units (mg/dL for fasting glucose, % for HbA1c), so glucose_measure and glucose_value predict only each other; diabetes represents glucose status in the other models.

Value

An essential8_imputation_setup object, a list with the prepared data and the mice arguments method, predictorMatrix, where, visitSequence, and post, plus inputs, a data frame describing each input: the rows it applies to, the values to impute, and the method.

See Also

score_le8() and its impute argument to impute and score in one call; le8_imputation_control(); score_le8_imputed() to score your own mice run.

Examples


adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
adults$non_hdl_cholesterol[c(2, 5)] <- NA
adults$sleep_hours[3] <- NA

setup <- le8_imputation_setup(adults)
setup

# Adjust the settings, then run mice yourself: here, sleep hours are no
# longer predicted from age. Keep predictive mean matching for numeric
# inputs; methods such as "norm" can impute values outside their valid
# range, which score_le8() then rejects.
setup$predictorMatrix["sleep_hours", "age"] <- 0
imputed <- mice::mice(
  setup$data,
  m = 5,
  method = setup$method,
  predictorMatrix = setup$predictorMatrix,
  where = setup$where,
  visitSequence = setup$visitSequence,
  post = setup$post,
  remove.collinear = FALSE,
  remove.constant = FALSE,
  seed = 1,
  printFlag = FALSE
)
summary(score_le8_imputed(imputed))


Plot LE8 scores

Description

Draws the scores returned by score_le8() with ggplot2:

Dashed lines mark the moderate (50) and high (80) thresholds. Missing scores are left out. The result is a ggplot object, so it can be modified with further ggplot2 layers, scales, and themes. For other designs, start from tidy().

Usage

## S3 method for class 'essential8_scores'
plot(
  x,
  type = c("components", "distribution", "composite", "forest"),
  by = NULL,
  ...
)

Arguments

x

An essential8_scores object returned by score_le8().

type

The plot to draw: "components", "distribution", "composite", or "forest".

by

For type = "forest", an optional column name in x whose groups are compared, such as "sex". Defaults to the grouping column of a tibble grouped by one column, and to none otherwise.

...

For type = "forest", named arguments passed to ggforestplotR::ggforestplot(). Must be empty for other types.

Value

A ggplot object.

Forest plots

For type = "forest", each row is a measure: the mean score and its t-based confidence interval, from the rows with that score available. Measures with fewer than two available scores in a group have no interval and are left out. With by, rows with a missing group are left out, and groups are ordered by factor level (or sorted, for other columns).

Imputed scores

For scores from score_le8_imputed(), "components" shows pooled means and "forest" pooled means with Rubin's-rules confidence intervals. "distribution" shows the stacked imputed data sets, and "composite" weights each row by 1/m so the bars count participants.

Arguments in ... are passed to ggforestplotR::ggforestplot(), so its styling options work as usual, for example striped_rows = TRUE, point_size, dodge_width, ref_line, or sort_terms. conf.level (default 0.95) sets the interval level as well as the label. The data mapping arguments (data, term, estimate, conf.low, conf.high, label, group, and n) are set by plot(). Composition helpers such as ggforestplotR::add_forest_table() can be added to the result.

See Also

tidy.essential8_scores(), summary.essential8_scores()

Examples


adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
scores <- score_le8(adults)

plot(scores)
plot(scores, type = "distribution")
plot(scores, type = "composite")



# Compare groups in a forest plot, passing styling to ggforestplotR.
plot(scores, type = "forest", by = "bmi_profile", striped_rows = TRUE)


Objects exported from other packages

Description

These objects are imported from other packages. Follow the links below to see their documentation.

generics

tidy()


Score Life's Essential 8 cardiovascular health

Description

Computes the eight Life's Essential 8 (LE8) component scores and the composite score using the American Heart Association's 2022 Presidential Advisory. Rows aged 20 years or older are scored with the adult definitions; rows aged 4 months to 19 years are scored with the pediatric definitions. Component scores are calculated wherever sufficient inputs are available, without imputing missing values.

Usage

score_le8(
  data,
  diet_method = "mepa",
  mepa_columns = NULL,
  min_components = 7L,
  dash_columns = NULL,
  dash_cutpoints = NULL,
  hei2015_columns = NULL,
  hei2015_cutpoints = NULL,
  reference = "nhanes_2015_2018",
  impute = FALSE
)

Arguments

data

A data frame with one row per person (or visit) and the input columns described below. Adults and children may be mixed.

diet_method

A single diet-scoring method applied to every row in data: "mepa" (the default), "dash", "hei2015", or "percentile". Values are matched case-insensitively. Score data that use different methods in separate calls.

mepa_columns

NULL, or a named character vector mapping canonical MEPA fields to columns in data. The names are canonical fields (the 16 screener items, sex, and milk_source) and the values are actual column names. Unmapped fields use their canonical names.

min_components

A single integer from 1 to 8 specifying the minimum number of non-missing LE8 component scores required to calculate le8_composite_score. The default is 7. Available component scores are averaged without imputation, which treats a missing component as equal to the average of the others; observations below the threshold receive NA_real_. Pediatric data usually need a lower value; see Pediatric scoring. To account for missing inputs instead, use impute.

dash_columns, hei2015_columns

NULL, or named character vectors mapping canonical DASH or HEI-2015 fields to columns in data. Unmapped fields default to the canonical name prefixed with dash_ or hei2015_. Names and input column names are matched case-insensitively.

dash_cutpoints

NULL to use the packaged DASH intake quintiles and total-score cutpoints, or a named list containing the eight canonical DASH fields and total. Each intake vector contains four nondecreasing reference quintile cutpoints (20th, 40th, 60th, 80th percentiles), in the same units as the inputs. total contains four nondecreasing reference DASH-total cutpoints (25th, 50th, 75th, 95th percentiles), each from 8 to 40. Tied cutpoints are allowed. Explicit cutpoints bypass reference and use inputs in their supplied units, without energy standardization, preserving existing calls.

hei2015_cutpoints

NULL to use reference, or four nondecreasing reference HEI-2015-total cutpoints (25th, 50th, 75th, 95th percentiles), each from 0 to 100. Tied cutpoints are allowed.

reference

"nhanes_2015_2018" (the default), or a method-matched diet_reference() object. Used for already-computed indices and raw intake scoring when explicit cutpoints are absent. Raw DASH requires the packaged reference's intake quintiles; for other DASH definitions, supply dash_cutpoints. Direct percentiles and explicit raw cutpoints bypass reference lookup. The built-in references describe nonpregnant adults aged 20+ with two reliable recalls; they are derived estimates, not AHA-published cutpoints, and are refused for pediatric rows.

impute

Whether to multiply impute missing inputs before scoring: FALSE (the default), TRUE for the default settings, or le8_imputation_control() to set the number of imputations, a seed, auxiliary predictors, and other mice::mice() arguments. Requires the mice package and diet_method = "mepa". See Multiple imputation.

Value

An essential8_scores object: data, with its original class (so tibbles and grouped tibbles are returned as such) and columns, plus mepa_total (items met on the age-appropriate MEPA screener: 0-16 from age 6, 0-10 at ages 2-5, 0-6 at 6-23 months), dash_total, and hei2015_total (missing unless calculated from the corresponding raw inputs), physical_activity_moderate_equivalent_minutes (weekly minutes used for adults and children aged 6+), the eight component scores (diet_score, physical_activity_score, nicotine_score, sleep_score, bmi_score, blood_lipids_score, blood_glucose_score, and blood_pressure_score), n_components, le8_composite_score, le8_complete, le8_category, and le8_population ("adult" or "pediatric"). The component count reports how many scores contributed to the composite score; le8_complete is TRUE only when all eight components are available. Categories are "low" for scores below 50, "moderate" for scores from 50 to less than 80, and "high" for scores of at least 80. The category is missing when the composite score is missing. For raw DASH calls, the eight component scores (1 to 5 points each) are also appended as ⁠dash_<field>_score⁠; they sum to dash_total. For raw HEI-2015 calls, the 13 component scores are also appended as ⁠hei2015_<component>_score⁠, including fatty_acids and saturated_fats.

With impute, an essential8_imputed_scores object instead: the scored completed data sets stacked, with the imputation number in .imp and the row of data in .id. It is a data frame, or a tibble for tibble input (ungrouped). The mids object from mice is kept as attr(x, "mids") for diagnostics, for example plot(attr(x, "mids")) to check convergence.

data must not already contain any of these output columns (compared case-insensitively), or the le8_-prefixed component names used by essential8 0.3.0 and earlier; rename or remove them first.

The essential8_scores class adds summary(), tidy(), plot(), and dplyr summarise() methods. See as_le8_scores() for when the class is kept and how to restore it.

Diet scoring methods

MEPA retains the individual assessment pathway. For population research, diet_method = "dash" accepts an already-computed index in dash, and diet_method = "hei2015" accepts an already-computed index in hei2015. Either method alternatively accepts a percentile in diet_value (0 to 100). Both methods also calculate raw totals from the intake fields below, using the packaged reference by default. Raw HEI-2015 also accepts a custom diet_reference(); raw DASH supports custom definitions via dash_cutpoints. Do not supply both the index column and an observed percentile; an entirely missing diet_value column is ignored. Data with no diet inputs retain the package's usual missing-component behavior. Once raw scoring is selected, every raw input column must be present (values may be missing); an absent column is an error rather than a silently missing diet score.

An index is compared with fixed reference cutpoints to identify its percentile category. The package does not estimate an exact percentile from four cutpoints, or rank the current cohort against itself. Specify reference = "nhanes_2015_2018" explicitly in reproducible analyses.

The built-in DASH reference is specifically the 8-to-40 Fung-style FPED construction identified as essential8_fung_fped_v1; it requires matching food definitions, pooled weighted intake quintiles, and tie handling. Other DASH definitions need a custom reference. HEI-2015 indices must be constructed using an appropriate established method; the built-in reference uses individual scoring after averaging the same two recalls' constituents and energy. It is not a usual-intake or population-ratio estimate. Both references use NHANES 2015-2016 and 2017-2018, two-day dietary weights divided by two, and the NHANES strata and PSU design. Detailed methodology, source URLs, hashes, sample counts, and index definitions accompany the references and the maintainer script data-raw/build_diet_references.R in the repository.

Fractional inputs confined to 0-1 (other than endpoints alone) are rejected as apparent proportions; supply percentile points, such as 95, not 0.95. This safeguard also rejects a batch consisting only of genuine fractional percentiles below 1. Values are never automatically multiplied by 100.

Supply one input pathway per call: raw intake, a precomputed index, or a percentile. Raw intake fields cannot be combined with a precomputed index or observed percentile. Raw fields are food-group and nutrient summaries, prepared before scoring; the function does not parse dietary-recall files. See vignette("population-diets") for executable examples and units.

Input columns

The column names below are case-sensitive; a name that differs only by case (for example BMI) is an error. MEPA, DASH, and HEI-2015 diet fields are matched case-insensitively. A column whose values are all missing may be logical NA (as read.csv() produces for a blank column). Columns that only apply to adults or only to children are ignored for other rows.

Component input columns may contain missing values or be omitted. A component score is NA_real_ when its available inputs are insufficient. Missing values are never imputed. A warning is emitted when an entire LE8 component cannot be calculated for any observation where AHA defines it.

Pediatric scoring

Rows aged 4 months to 19 years use the children column of Table 1 of the advisory and the suggested rules for younger children in its Supplemental Appendix 2:

Components AHA does not define at a row's age are NA and are not counted toward min_components; a message notes any such inputs that were supplied. AHA recommends averaging the components that are available and appropriate for measurement in children (the NHANES analysis averaged as few as three), so pediatric analyses usually set a lower min_components. add_pediatric_references() can derive the growth-chart and blood-pressure reference inputs. See vignette("pediatric-scoring").

Where the sources conflict, the package follows the more specific rule: the supplement's 2-5 year diet rule (10 points per item) rather than the Table 1 bands; and, for 6-23 month weight, the supplement's explicit 0-point worst state (at or above the 99.7th percentile with rapid gain) rather than its decrements, which would leave 25. Nineteen-year-olds use the 13-18 year sleep range (8 to 10 hours), the last range AHA lists.

Pediatric input columns

Optional clinical-judgment columns

Source-constrained behavior

The function derives the 0-to-16 MEPA total from the 16 raw screener responses. Raw DASH scoring uses the eight-component Fung index: five food groups receive 1 to 5 points by intake quintile; sodium, red/processed meat, and sweetened beverages receive 5 to 1. Intakes equal to a quintile cutpoint stay in the lower quintile. Their sum is dash_total (8 to 40).

Raw HEI-2015 calls compute 13 density, fatty-acid-ratio, and energy-percentage components with proportional scoring between the published standards. Added sugars use 16 kcal per teaspoon equivalent; saturated fat uses 9 kcal per gram. Scores are capped at each component's maximum. Their sum is hei2015_total (0 to 100), which is distinct from the LE8 diet score. With zero saturated fat and positive unsaturated fat, the fatty-acid component receives 10 points; with all three fats zero it receives zero, following the NCI scoring macro. Missing inputs are never treated as zero; a total requires all of its diet components, regardless of min_components.

Raw DASH and HEI-2015 totals are converted to LE8 scores of 0, 25, 50, 80, or 100 using fixed reference total-score cutpoints. Equality enters the higher LE8 band. Explicit cutpoints override the packaged reference and must come from a suitable fixed reference population, using appropriate survey weights and strata where applicable. Cutpoints are never inferred from data. For references requiring different cutpoints by stratum, score strata in separate calls. Alternatively, diet_method = "percentile" accepts externally calculated DASH or HEI-2015 percentiles. The rows in data are never ranked against one another.

The AHA table applies 20-point treatment decrements to blood-lipid and blood-pressure scores. These components are floored at zero, consistent with the AHA's 0-to-100 metric definition. Optional sleep-apnea and prediabetes/metformin decrements are applied only through explicit flags. Inputs are not rounded. The documented MEPA daily/weekly equivalences are applied where the source question and criterion use different timeframes. Combinations without a source-defined score, including simultaneous current combustible smoking and current inhaled-NDS use, produce a structured error.

Input errors inherit from essential8_input_error and essential8_error. General and adult errors also carry essential8_adult_input_error, as in earlier versions; pediatric-only errors carry essential8_pediatric_input_error.

Multiple imputation

With impute, score_le8() fills in missing inputs with mice::mice() several times, scores every completed data set, and returns them stacked. The imputation:

  1. checks the observed values, so data that cannot be scored stop before imputation;

  2. imputes an input only for participants whose age uses it (adult BMI is never imputed for a child, for example), predicting it from age, the other inputs available for the same participants, and any auxiliary columns;

  3. uses predictive mean matching for numeric inputs, so imputed values are always values observed in someone else, and logistic or multinomial regression for categorical inputs;

  4. never imputes a combination the AHA scoring rules do not score, such as diagnosed diabetes without an HbA1c, current smoking with current inhaled-NDS use, or a fasting glucose of 126 mg/dL or more without diagnosed diabetes.

min_components then applies to each completed data set as usual. summary(), dplyr summarise(), and plot() pool the results across imputations with Rubin's rules. See le8_imputation_setup() for the full rules, and to inspect or adjust them.

Imputation assumes values are missing at random given the variables in the imputation models; include the variables used in later analyses, such as exposures and outcomes, with le8_imputation_control(auxiliary = ).

References

Lloyd-Jones DM, Allen NB, Anderson CAM, et al. (2022). Life's Essential 8: Updating and Enhancing the American Heart Association's Construct of Cardiovascular Health. Circulation, 146(5), e18-e43. doi:10.1161/CIR.0000000000001078

Lloyd-Jones DM, Ning H, Labarthe D, et al. (2022). Status of Cardiovascular Health in US Adults and Children Using the American Heart Association's New Life's Essential 8 Metrics. Circulation, 146(11), 822-835. doi:10.1161/CIRCULATIONAHA.122.060911

Flynn JT, Kaelber DC, Baker-Smith CM, et al. (2017). Clinical Practice Guideline for Screening and Management of High Blood Pressure in Children and Adolescents. Pediatrics, 140(3), e20171904. doi:10.1542/peds.2017-1904

Fung TT, Chiuve SE, McCullough ML, et al. (2008). Adherence to a DASH-Style Diet and Risk of Coronary Heart Disease and Stroke in Women. Archives of Internal Medicine, 168(7), 713-720. doi:10.1001/archinte.168.7.713

Krebs-Smith SM, Pannucci TE, Subar AF, et al. (2018). Update of the Healthy Eating Index: HEI-2015. Journal of the Academy of Nutrition and Dietetics, 118(9), 1591-1602. doi:10.1016/j.jand.2018.05.021 See also the National Cancer Institute's scoring standards and algorithm.

See Also

summary.essential8_scores(), tidy.essential8_scores(), and plot.essential8_scores() to summarize, reshape, and plot the scores; add_pediatric_references() to derive pediatric growth-chart and blood-pressure inputs; diet_reference() for custom diet references.

Examples


library(dplyr)

patient <- tibble(
  id = "patient_1",
  age = 55,
  sex = "female",
  # Daily servings
  olive_oil = 2,
  green_leafy_vegetables = 1,
  other_vegetables = 2,
  whole_grains = 2,
  # Weekly servings
  berries = 3,
  other_fruit = 5,
  meat = 2,
  fish = 3,
  chicken = 2,
  cheese = 1,
  butter_cream = 1,
  beans = 3,
  sweets_and_pastries = 1,
  nuts = 4,
  alcohol = 4,
  # Fast-food meals per week
  fast_food = 0,
  moderate_activity_minutes = 90,
  vigorous_activity_minutes = 0,
  smoking_status = "former",
  years_since_quit = 6,
  current_inhaled_nds = FALSE,
  secondhand_smoke_home = FALSE,
  sleep_hours = 7.5,
  bmi = 27.5,
  bmi_profile = "general",
  non_hdl_cholesterol = 145,
  lipid_lowering_treatment = FALSE,
  diabetes = FALSE,
  glucose_measure = "fasting_glucose",
  glucose_value = 95,
  systolic_bp = 128,
  diastolic_bp = 78,
  antihypertensive_treatment = FALSE
)

scores <- score_le8(patient, diet_method = "mepa")
select(scores, id, mepa_total, diet_score, le8_composite_score,
       le8_category)

# A 4-year-old with the preschool diet screener and no laboratory values.
child <- tibble(
  id = "child_1",
  age = 4,
  # Ten MEPA items apply at ages 2-5; sweets include sugary drinks.
  green_leafy_vegetables = 1, other_vegetables = 1, # servings per day
  berries = 7, other_fruit = 14,                     # servings per week
  whole_grains = 2, olive_oil = 1,                   # servings per day
  sweets_and_pastries = 2, meat = 2, fish = 1,       # servings per week
  nuts = 2, butter_cream = 1,
  fast_food = 0.25,                                  # times per week
  active_play_minutes = 160,
  smoking_status = "never", current_inhaled_nds = FALSE,
  secondhand_smoke_home = FALSE,
  sleep_hours = 11,
  bmi_percentile = 60, bmi_percent_of_p95 = 85,
  systolic_bp = 98, diastolic_bp = 58,
  systolic_bp_p90 = 103, systolic_bp_p95 = 107,
  diastolic_bp_p90 = 63, diastolic_bp_p95 = 67,
  antihypertensive_treatment = FALSE
)

child_scores <- score_le8(child, min_components = 5)
select(child_scores, id, mepa_total, ends_with("_score"), n_components)



# Multiply impute missing inputs, then pool the scores.
adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
adults$non_hdl_cholesterol[c(2, 5)] <- NA

imputed <- score_le8(adults, impute = le8_imputation_control(m = 5, seed = 1))
summary(imputed)


Score multiply imputed LE8 inputs

Description

Scores every completed data set from a multiple imputation and returns them stacked, with the imputation number in .imp. Methods for the result pool across imputations with Rubin's rules: summary() and, with dplyr, summarise() report pooled means with confidence intervals, and plot(type = "forest") draws pooled intervals.

Usage

score_le8_imputed(data, ...)

Arguments

data

A mids object from mice::mice() (for example, run with the settings from le8_imputation_setup()), or a data frame of stacked completed data sets with an integer .imp column numbering them from 1 (for example, from mice::complete(imputed, "long") or another imputation package). To impute and score in one call, use score_le8(impute = TRUE) instead.

...

Arguments passed to score_le8(), such as min_components.

Value

An essential8_imputed_scores object: the stacked scored data sets, a subclass of essential8_scores. Its summary(), summarise(), tidy(), and plot() methods account for the imputations.

Pooling

Each statistic is estimated in every imputed data set and combined with Rubin's rules. Means are pooled with total variance T = \bar{U} + (1 + 1/m) B and Barnard-Rubin degrees of freedom; the fraction of missing information (fmi) describes how much the imputations add to the uncertainty. Category percentages are pooled the same way. Standard deviations and quantiles are averaged across imputations, which describes the distribution but carries no interval.

See Also

le8_imputation_setup()

Examples


adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
adults$non_hdl_cholesterol[c(2, 5)] <- NA

# Stacked completed data sets, as any imputation software might return.
completed <- function(imp, value) {
  out <- adults
  out$non_hdl_cholesterol[is.na(out$non_hdl_cholesterol)] <- value
  cbind(.imp = imp, out)
}
stacked <- rbind(completed(1L, 150), completed(2L, 170))
summary(score_le8_imputed(stacked))


Summarise multiply imputed LE8 scores with dplyr

Description

The summarise() method for scores from score_le8_imputed(). Without expressions, it returns the pooled statistics in summary(), one row per measure and group. With expressions, it is ordinary dplyr on the stacked data sets; add .imp to .by to summarise each imputation separately.

Usage

## S3 method for class 'essential8_imputed_scores'
summarise(.data, ..., .by = NULL, .groups = NULL)

Arguments

.data

An essential8_imputed_scores object.

...

Summary expressions. If any are supplied, the call is handled by dplyr::summarise().

.by

<tidy-select> Optional columns to group by for this summary.

.groups

Passed to dplyr::summarise() when ... is supplied. Otherwise ignored; the LE8 summary is always ungrouped.

Value

Without expressions, an ungrouped data frame with the grouping columns, measure, and the pooled statistics: n, n_missing, mean, std.error, conf.low, conf.high (95%), df, fmi, and the averaged sd, min, q25, median, q75, and max. With expressions, the result of dplyr::summarise().

See Also

summary.essential8_imputed_scores()


Summarise LE8 scores with dplyr

Description

With dplyr loaded, calling summarise() (or summarize()) on scores from score_le8() without any summary expressions returns the statistics in summary() as a data frame, one row per measure and group. Calls with expressions, such as summarise(scores, mean = mean(le8_composite_score)), are passed to dplyr unchanged.

Groups come from .by, or from the grouping of a grouped tibble passed to score_le8(). Because group_by() drops the essential8_scores class, use .by for grouped summaries of scored data, or restore the class with as_le8_scores().

Usage

## S3 method for class 'essential8_scores'
summarise(.data, ..., .by = NULL, .groups = NULL)

Arguments

.data

An essential8_scores object returned by score_le8().

...

Summary expressions. If any are supplied, the call is handled by dplyr::summarise().

.by

<tidy-select> Optional columns to group by for this summary.

.groups

Passed to dplyr::summarise() when ... is supplied. Otherwise ignored; the LE8 summary is always ungrouped.

Value

Without expressions, an ungrouped data frame of the same type as .data (a tibble for tibble input) with the grouping columns, measure (a factor: composite, then the eight components in AHA order), and the statistics n (available scores), n_missing, mean, sd, min, q25, median, q75, and max. With expressions, the result of dplyr::summarise().

See Also

summary.essential8_scores(), tidy.essential8_scores()

Examples


library(dplyr)

adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
scores <- adults |>
  select(!starts_with("expected_")) |>
  score_le8()

summarise(scores)
summarise(scores, .by = bmi_profile)

# Ordinary dplyr summaries work as usual.
summarise(scores, mean_le8 = mean(le8_composite_score), .by = bmi_profile)


Summarize multiply imputed LE8 scores

Description

Pools the scores from score_le8(impute = TRUE) or score_le8_imputed() across imputations with Rubin's rules. Means and category percentages get pooled confidence intervals and the fraction of missing information; standard deviations and quantiles are averaged across imputations. Counts are per participant (averaged across imputations), not per stacked row.

Usage

## S3 method for class 'essential8_imputed_scores'
summary(object, conf_level = 0.95, ...)

## S3 method for class 'summary.essential8_imputed_scores'
print(x, digits = 1, ...)

Arguments

object

An essential8_imputed_scores object from score_le8_imputed().

conf_level

Confidence level for the pooled intervals.

...

Not used.

x

A summary.essential8_imputed_scores object.

digits

Number of decimal places to print.

Value

summary() returns a summary.essential8_imputed_scores object, a list with n (participants), m (imputations), population, n_composite, n_complete, statistics (one row per measure with n, n_missing, pooled mean, std.error, conf.low, conf.high, df, and fmi, and averaged sd, min, q25, median, q75, and max), categories (pooled percentages with confidence intervals), conf_level, and settings. print() returns x invisibly.

See Also

score_le8_imputed(), summary.essential8_scores()

Examples


adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
adults$non_hdl_cholesterol[c(2, 5)] <- NA

scores <- score_le8(
  adults,
  impute = le8_imputation_control(m = 5, seed = 1)
)
summary(scores)
summary(scores)$statistics


Summarize LE8 scores

Description

Summarizes the composite and component scores returned by score_le8(): how many rows were scored, the distribution of each score, and the cardiovascular health categories. Grouping is ignored; use summarise() for summaries by group.

Usage

## S3 method for class 'essential8_scores'
summary(object, ...)

## S3 method for class 'summary.essential8_scores'
print(x, digits = 1, ...)

Arguments

object

An essential8_scores object returned by score_le8().

...

Not used.

x

A summary.essential8_scores object.

digits

Number of decimal places to print.

Value

summary() returns a summary.essential8_scores object, a list with:

print() returns x invisibly.

See Also

tidy.essential8_scores(), summarise.essential8_scores(), plot.essential8_scores()

Examples

adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
scores <- score_le8(adults)
summary(scores)

# The statistics are also available as a data frame.
summary(scores)$statistics

Tidy LE8 scores into long format

Description

Reshapes the composite and component scores returned by score_le8() into long format, with one row per input row and measure. This is the shape ggplot2 and grouped summaries expect.

Usage

## S3 method for class 'essential8_scores'
tidy(x, id_cols = NULL, composite = TRUE, ...)

Arguments

x

An essential8_scores object returned by score_le8().

id_cols

Optional character vector of columns in x to carry into the result, such as a participant identifier. Defaults to the grouping columns when x is a grouped tibble, and to none otherwise. Scores from score_le8_imputed() always carry .imp (and .id, when present).

composite

Whether to include the composite score as a measure.

...

Not used.

Value

A data frame of the same type as x (a tibble for tibble input), ungrouped, with the columns:

See Also

summary.essential8_scores(), plot.essential8_scores()

Examples

adults <- read.csv(system.file(
  "extdata", "le8-adult-example.csv", package = "essential8"
))
adults <- adults[!startsWith(names(adults), "expected_")]
scores <- score_le8(adults)
head(tidy(scores, id_cols = "id"), 9)