Mapping Study Physical Activity to NHANES Quantiles

library(mapnhanespa)

Purpose

mapnhanespa maps physical activity summaries from a study sample onto population-level quantiles estimated from the National Health and Nutrition Examination Survey (NHANES) 2011-2012 and 2013-2014 accelerometer waves. These NHANES cycles are useful reference populations because participants wore ActiGraph GT3X+ accelerometers on the non-dominant wrist for seven consecutive days, producing nationally representative accelerometry data.

The package is designed for the common setting where a study has participant identifiers, age, sex or gender, a physical activity measure, and a value for that measure. Instead of comparing raw values across measures with different scales, the package evaluates each value against the corresponding NHANES cumulative distribution function (CDF). The result is a quantile in [0, 1] that can be interpreted relative to the NHANES reference distribution.

The CDFs in this package are based on NHANES 2011-2014 activity count, MIMS, and step-count summaries. The step-count measures relate to work applying multiple step-counting algorithms to high-resolution wrist accelerometry data from NHANES 2011-2014 (Koffman, Crainiceanu, and Muschelli 2025). The minute-level NHANES step count and physical activity data are also available through PhysioNet (Koffman and Muschelli 2025).

Basic Mapping

Use map_nhanes_pa_quantiles() when the input data have one row per participant-measure observation.

study_data <- data.frame(
  id = c("P01", "P02", "P03"),
  age = c(25, 62, 84),
  sex = c("Female", "Male", "Female"),
  measure = c("mims", "ssl_steps", "AC"),
  value = c(15000, 7500, 1000000)
)

map_nhanes_pa_quantiles(study_data, id = "id")
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             [20,30)       0.5349443
#> 2 P02  62   Male ssl_steps    7500             [60,70)       0.3527381
#> 3 P03  84 Female        AC 1000000             [80,85)       0.1322205

The returned age_category_pa_map column shows the NHANES age category used to select each participant’s CDF. The following example covers all nine supported summaries:

all_measures <- data.frame(
  id = rep("P01", 9),
  age = 25,
  sex = "Female",
  measure = c("total_activity_counts", "total_log10AC", "total_PAXMTSM",
              "total_log10PAXMTSM", "total_scsslsteps", "total_scrfsteps",
              "total_oaksteps", "total_vssteps", "total_vsrevsteps"),
  value = c(2773035, 3039, 14653, 1043, 8694, 11421, 12055, 9505, 9631)
)

map_nhanes_pa_quantiles(all_measures, id = "id")
#>    id age    sex               measure   value age_category_pa_map
#> 1 P01  25 Female total_activity_counts 2773035             [20,30)
#> 2 P01  25 Female         total_log10AC    3039             [20,30)
#> 3 P01  25 Female         total_PAXMTSM   14653             [20,30)
#> 4 P01  25 Female    total_log10PAXMTSM    1043             [20,30)
#> 5 P01  25 Female      total_scsslsteps    8694             [20,30)
#> 6 P01  25 Female       total_scrfsteps   11421             [20,30)
#> 7 P01  25 Female        total_oaksteps   12055             [20,30)
#> 8 P01  25 Female         total_vssteps    9505             [20,30)
#> 9 P01  25 Female      total_vsrevsteps    9631             [20,30)
#>   nhanes_quantile
#> 1       0.4852706
#> 2       0.5714842
#> 3       0.4873396
#> 4       0.5564848
#> 5       0.5872852
#> 6       0.4938108
#> 7       0.4892558
#> 8       0.5019565
#> 9       0.5158600

The complete list of accepted names and the summary used for each CDF is available from nhanes_pa_measure_map(). Other names return NA with a warning listing the unmapped measures. Each value should be calculated using the summary named in the map and supplied on that summary’s scale.

nhanes_pa_measure_map()
#>                    measure      summary
#> 1                       AC           AC
#> 2          activity_counts           AC
#> 3           activitycounts           AC
#> 4                   counts           AC
#> 5                 total_AC           AC
#> 6    total_activity_counts           AC
#> 7             total_counts           AC
#> 8                  log10AC      log10AC
#> 9    log10_activity_counts      log10AC
#> 10            log10_counts      log10AC
#> 11           total_log10AC      log10AC
#> 12                 PAXMTSM      PAXMTSM
#> 13                    mims      PAXMTSM
#> 14               mims_unit      PAXMTSM
#> 15           total_PAXMTSM      PAXMTSM
#> 16            log10PAXMTSM log10PAXMTSM
#> 17              log10_mims log10PAXMTSM
#> 18      total_log10PAXMTSM log10PAXMTSM
#> 19         log10_mims_unit log10PAXMTSM
#> 20              scsslsteps   scsslsteps
#> 21               ssl_steps   scsslsteps
#> 22            sslstepcount   scsslsteps
#> 23           sslstepcounts   scsslsteps
#> 24         total_ssl_steps   scsslsteps
#> 25        total_scsslsteps   scsslsteps
#> 26     steps_stepcount_ssl   scsslsteps
#> 27    steps_stepcounts_ssl   scsslsteps
#> 28               scrfsteps    scrfsteps
#> 29                rf_steps    scrfsteps
#> 30             rfstepcount    scrfsteps
#> 31            rfstepcounts    scrfsteps
#> 32          total_rf_steps    scrfsteps
#> 33         total_scrfsteps    scrfsteps
#> 34      steps_stepcount_rf    scrfsteps
#> 35     steps_stepcounts_rf    scrfsteps
#> 36                oaksteps     oaksteps
#> 37             foreststeps     oaksteps
#> 38               steps_oak     oaksteps
#> 39            steps_forest     oaksteps
#> 40              nsteps_oak     oaksteps
#> 41           nsteps_forest     oaksteps
#> 42          total_oaksteps     oaksteps
#> 43  steps_stepcount_forest     oaksteps
#> 44 steps_stepcounts_forest     oaksteps
#> 45                 vssteps      vssteps
#> 46        vssteps_original      vssteps
#> 47       steps_vs_original      vssteps
#> 48           total_vssteps      vssteps
#> 49              vsrevsteps   vsrevsteps
#> 50         vssteps_revised   vsrevsteps
#> 51        steps_vs_revised   vsrevsteps
#> 52        total_vsrevsteps   vsrevsteps

The measure column accepts common aliases, including total_ac and total_activity_counts for the AC CDF:

measures <- data.frame(
  id = rep("P01", 4),
  age = 25,
  sex = "Female",
  measure = c("mims", "PAXMTSM", "total_ac", "total_activity_counts"),
  value = c(15000, 15000, 2773035, 2773035)
)

map_nhanes_pa_quantiles(measures, id = "id")
#>    id age    sex               measure   value age_category_pa_map
#> 1 P01  25 Female                  mims   15000             [20,30)
#> 2 P01  25 Female               PAXMTSM   15000             [20,30)
#> 3 P01  25 Female              total_ac 2773035             [20,30)
#> 4 P01  25 Female total_activity_counts 2773035             [20,30)
#>   nhanes_quantile
#> 1       0.5349443
#> 2       0.5349443
#> 3       0.4852706
#> 4       0.4852706

nhanes_pa_measure_cdf("total_activity_counts", age = 25, sex = "Female")(2773035)
#> [1] 0.4852706

Combined and Wave-Specific References

By default, quantiles are evaluated against CDFs estimated from the combined 2011-2012 and 2013-2014 NHANES waves.

map_nhanes_pa_quantiles(study_data, id = "id")
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             [20,30)       0.5349443
#> 2 P02  62   Male ssl_steps    7500             [60,70)       0.3527381
#> 3 P03  84 Female        AC 1000000             [80,85)       0.1322205

To map against a specific NHANES wave, provide wave. Supported values include the NHANES data release cycles 7 and 8, and the year labels "2011-2012" and "2013-2014".

map_nhanes_pa_quantiles(study_data, id = "id", wave = "2013-2014")
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             [20,30)       0.4943653
#> 2 P02  62   Male ssl_steps    7500             [60,70)       0.3820584
#> 3 P03  84 Female        AC 1000000             [80,85)       0.1181001

Overall Age or Sex Strata

If a study should be mapped without sex or gender stratification, set sex = NULL. The participant’s age category is still used, but the CDF is selected from the gender == "Overall" stratum.

map_nhanes_pa_quantiles(study_data, id = "id", sex = NULL)
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             [20,30)       0.5688587
#> 2 P02  62   Male ssl_steps    7500             [60,70)       0.4164160
#> 3 P03  84 Female        AC 1000000             [80,85)       0.1408881

If a study should be mapped without age stratification, set age = NULL. The participant’s sex or gender is still used, but the CDF is selected from the cat_age == "Overall" stratum.

map_nhanes_pa_quantiles(study_data, id = "id", age = NULL)
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             Overall      0.53548286
#> 2 P02  62   Male ssl_steps    7500             Overall      0.28321363
#> 3 P03  84 Female        AC 1000000             Overall      0.01040967

Both options can be combined with a wave-specific reference:

map_nhanes_pa_quantiles(study_data, id = "id", sex = NULL, wave = 7)
#>    id age    sex   measure   value age_category_pa_map nhanes_quantile
#> 1 P01  25 Female      mims   15000             [20,30)       0.6017452
#> 2 P02  62   Male ssl_steps    7500             [60,70)       0.3716006
#> 3 P03  84 Female        AC 1000000             [80,85)       0.1669768

The package data do not contain a stratum that is overall for both age and sex or gender. Calls that omit both age and sex therefore produce an error.

Wear-time Inclusion Criteria

The default NHANES reference follows the primary analysis of Koffman, Crainiceanu, and Muschelli (2025). A day is valid if it has at least 1,368 minutes (95% of a full day) of non-flagged wear, at least 420 minutes of wake wear, and at least 420 minutes of non-zero MIMS. Participants need at least 3 valid days.

Studies often use other rules, and a quantile is most meaningful when the study and the reference use the same rules. The min_wear_minutes and min_valid_days arguments select a reference built with a different criterion. Survey weights were re-adjusted separately for each criterion. The available criteria are listed by nhanes_pa_wear_criteria():

criteria <- nhanes_pa_wear_criteria()
criteria[, c("criterion", "min_wear_hours", "pct_of_day", "min_valid_days",
             "default")]
#>         criterion min_wear_hours pct_of_day min_valid_days default
#> 1   wear600_days1           10.0       41.7              1   FALSE
#> 2   wear600_days3           10.0       41.7              3   FALSE
#> 3   wear600_days4           10.0       41.7              4   FALSE
#> 4   wear960_days1           16.0       66.7              1   FALSE
#> 5   wear960_days3           16.0       66.7              3   FALSE
#> 6   wear960_days4           16.0       66.7              4   FALSE
#> 7  wear1296_days1           21.6       90.0              1   FALSE
#> 8  wear1296_days3           21.6       90.0              3   FALSE
#> 9  wear1296_days4           21.6       90.0              4   FALSE
#> 10 wear1368_days1           22.8       95.0              1   FALSE
#> 11 wear1368_days3           22.8       95.0              3    TRUE
#> 12 wear1368_days4           22.8       95.0              4   FALSE
#> 13 wear1440_days1           24.0      100.0              1   FALSE
#> 14 wear1440_days3           24.0      100.0              3   FALSE
#> 15 wear1440_days4           24.0      100.0              4   FALSE
unique(criteria[, c("min_wear_minutes", "note")])
#>    min_wear_minutes
#> 1               600
#> 4               960
#> 7              1296
#> 10             1368
#> 13             1440
#>                                                                                                                                                   note
#> 1  10 h/day; NHANES 2003-2006 hip-worn standard (Troiano et al. 2008 required >= 4 valid days; Saint-Maurice et al. 2020 JAMA required >= 1 valid day)
#> 4                                                                                                          16 h/day; used in 24-h wrist-worn protocols
#> 7                                                                                                                        21.6 h/day; 90% of a 24-h day
#> 10                                                                               22.8 h/day; 95% of a 24-h day; primary analysis (Koffman et al. 2025)
#> 13                                                                                                                             24 h/day; complete wear

For example, a study that used the 10-hour, 4-day hip-worn NHANES 2003-2006 rule can compare the same value under both references:

compare <- rbind(
  cbind(criterion = "1368 min, 3 days (default)",
        map_nhanes_pa_quantiles(study_data, id = "id")),
  cbind(criterion = "600 min, 4 days",
        map_nhanes_pa_quantiles(study_data, id = "id",
                                min_wear_minutes = 600, min_valid_days = 4))
)
compare[order(compare$id), c("id", "measure", "value", "criterion",
                             "nhanes_quantile")]
#>    id   measure   value                  criterion nhanes_quantile
#> 1 P01      mims   15000 1368 min, 3 days (default)       0.5349443
#> 4 P01      mims   15000            600 min, 4 days       0.6424329
#> 2 P02 ssl_steps    7500 1368 min, 3 days (default)       0.3527381
#> 5 P02 ssl_steps    7500            600 min, 4 days       0.3922628
#> 3 P03        AC 1000000 1368 min, 3 days (default)       0.1322205
#> 6 P03        AC 1000000            600 min, 4 days       0.1432384

The default criterion uses nhanes_measure_data, so results match earlier versions of the package. Every other criterion uses the matching subset of nhanes_measure_data_wear_criteria.

Single Values

For a single participant-measure value, use nhanes_pa_quantile().

nhanes_pa_quantile(
  value = 15000,
  age = 25,
  sex = "Female",
  measure = "mims"
)
#> [1] 0.5349443

The same combined, wave-specific, and overall-stratum options are available:

nhanes_pa_quantile(
  value = 15000,
  age = 25,
  sex = NULL,
  measure = "mims",
  wave = "2011-2012"
)
#> [1] 0.6017452

Age Categories

Ages are mapped into NHANES CDF age categories:

suppressWarnings(nhanes_pa_age_category(c(8, 25, 84, 90)))
#> [1] "[0,10)"  "[20,30)" "[80,85)" "[80,85)"

Ages greater than 85 are mapped to the oldest available category, "[80,85)", and produce a warning when age is supplied directly. If a study already has age categories, pass the column name through age_category.

References

Koffman, Lily, Ciprian Crainiceanu, and John Muschelli. 2025. “Comparing Step Counting Algorithms for High-Resolution Wrist Accelerometry Data in NHANES 2011-2014.” Medicine & Science in Sports & Exercise 57 (4): 746–55. https://doi.org/10.1249/MSS.0000000000003616.
Koffman, Lily, and John Muschelli. 2025. “Minute Level Step Counts and Physical Activity Data from the National Health and Nutrition Examination Survey (NHANES) 2011-2014.” PhysioNet, May. https://doi.org/10.13026/9n0r-tv02.