Movatterモバイル変換


[0]ホーム

URL:


Title:Aggregate and Disaggregate Continuous Parameters forCompartmental Models
Version:0.0.2
Description:A convenient framework for aggregating and disaggregating continuously varying parameters (for example, case fatality ratio, with age) for proper parametrization of lower-resolution compartmental models (for example, with broad age categories) and subsequent upscaling of model outputs to high resolution (for example, as needed when calculating age-sensitive measures like years-life-lost).
License:MIT + file LICENSE
Encoding:UTF-8
RoxygenNote:7.3.2
Depends:R (≥ 3.5.0)
Suggests:lintr, knitr, rmarkdown, ggplot2, roxygen2, wpp2019, testthat(≥ 3.0.0), patchwork
VignetteBuilder:knitr
Imports:data.table
Config/testthat/edition:3
URL:https://cmmid.github.io/paramix/
NeedsCompilation:no
Packaged:2025-06-10 14:21:42 UTC; carl
Author:Carl PearsonORCID iD [aut, cre], Simon ProctorORCID iD [aut], Lucy GoodfellowORCID iD [aut]
Maintainer:Carl Pearson <carl.ab.pearson@gmail.com>
Repository:CRAN
Date/Publication:2025-06-10 14:50:02 UTC

paramix: Aggregate and Disaggregate Continuous Parameters for Compartmental Models

Description

A convenient framework for aggregating and disaggregating continuously varying parameters (for example, case fatality ratio, with age) for proper parametrization of lower-resolution compartmental models (for example, with broad age categories) and subsequent upscaling of model outputs to high resolution (for example, as needed when calculating age-sensitive measures like years-life-lost).

Author(s)

Maintainer: Carl Pearsoncarl.ab.pearson@gmail.com (ORCID)

Authors:

See Also

Useful links:


Create the Blending and Distilling Object

Description

Based on model and output partitions, create a mixing partition andassociated weights. That table of mixing values can be used to properlydiscretize a continuously varying (or otherwise high resolution) parameter toa relatively low resolution compartmental stratification, and thensubsequently allocate the low-resolution model outcomes into the most likelyhigh-resolution output partitions.

Usage

alembic(  f_param,  f_pop,  model_partition,  output_partition,  pars_interp_opts = interpolate_opts(fun = stats::splinefun, kind = "point", method =    "natural"),  pop_interp_opts = interpolate_opts(fun = stats::approxfun, kind = "integral", method =    "constant", yleft = 0, yright = 0))

Arguments

f_param

a function,f(x) which transforms the feature (e.g. age),to yield the parameter values. Alternatively, adata.frame where the firstcolumn is the feature and the second is the parameter; seexy.coords() fordetails. If the latter, combined withpars_interp_opts to create aparameter function.

f_pop

likef_param, either a density function (though it doesnot have to integrate to 1 like a pdf) or adata.frame of values. If thelatter, it is treated as a series of populations within intervals, andthen interpolated withpop_interp_opts to create a density function.

model_partition

a numeric vector of cut points, which define thepartitioning that will be used in the model; must be length > 1

output_partition

the partition of the underlying feature; must belength > 1

pars_interp_opts

a list, minimally with an elementfun,corresponding to an interpolation function. Defaults tosplinefun()"natural" interpolation.

pop_interp_opts

likepars_interp_opts, but for density. Defaults toapproxfun() "constant" interpolation.

Details

Thealembic function creates a mixing table, which governs the conversionbetween model and output partitions. The mixing table adata.table::data.table() where each row corresponds to a mixing partitionc_i, which is the union of the model and output partitions - i.e. eachunique boundary is included. Within each row, there is aweight andrelpop entry, corresponding to

\textrm{weight}_i = \int_{c_i} f(x)\rho(x)\text{d}x

\textrm{relpop}_i = \int_{c_i} \rho(x)\text{d}x

wheref(x) corresponds to thef_param argument and\rho(x)corresponds to thef_pop argument.

This mixing table is used in theblend() anddistill() functions.

Whenblending, the appropriately weighted parameter for a model partitionis the sum of\textrm{weight}_i divided by the\textrm{relpop}_iassociated with mixing partition(s) in that model partition. This correspondsto the properly, population weighted average of that parameter over thepartition.

Whendistilling, model outcomes associated with weighted parameter frompartitionj are distributed to the output partitioni by the sumof weights in mixing partitions in bothj andi divided by thetotal weight inj. This corresponds to proportional allocationaccording to Bayes rule: the outcome in the model partition was relativelymore likely in the higher weight mixing partition.

Value

adata.table with columns:model_partition,output_partition,weight andrelpop. The first two columns identify partition lower bounds, for both the modeland output, the other values are associated with; the combination ofmodel_partition andoutput_partition forms a unique identifier, but individually theymay appear multiple times. Generally, this object is only useful as an inputto theblend() anddistill() tools.

See Also

blend()

distill()

Examples

ifr_levin <- function(age_in_years) {  (10^(-3.27 + 0.0524 * age_in_years))/100}age_limits <- c(seq(0, 69, by = 5), 70, 80, 101)age_pyramid <- data.frame(  from = 0:101, weight = ifelse(0:101 < 65, 1, .99^(0:101-64)))age_pyramid$weight[102] <- 0# flat age distribution, then 1% annual deaths, no one lives past 101ifr_alembic <- alembic(ifr_levin, age_pyramid, age_limits, 0:101)

Blend Parameters

Description

blend extracts aggregate parameters from analembic object.

Usage

blend(alembic_dt)

Arguments

alembic_dt

analembic() return value

Value

adata.table of with two columns:model_partition (partition lowerbounds) andvalue (parameter values for those partitions)

Examples

ifr_levin <- function(age_in_years) {  (10^(-3.27 + 0.0524 * age_in_years))/100}age_limits <- c(seq(0, 69, by = 5), 70, 80, 101)age_pyramid <- data.frame(  from = 0:101, weight = ifelse(0:101 < 65, 1, .99^(0:101-64)))age_pyramid$weight[102] <- 0# flat age distribution, then 1% annual deaths, no one lives past 101alembic_dt <- alembic(ifr_levin, age_pyramid, age_limits, 0:101)ifr_blend <- blend(alembic_dt)# the actual functionplot(  60:100, ifr_levin(60:100),  xlab = "age (years)", ylab = "IFR", type = "l")# the properly aggregated blockslines(  age_limits, c(ifr_blend$value, tail(ifr_blend$value, 1)),  type = "s", col = "dodgerblue")# naively aggregated blocksifr_naive <- ifr_levin(head(age_limits, -1) + diff(age_limits)/2)lines(  age_limits, c(ifr_naive, tail(ifr_naive, 1)),  type = "s", col = "firebrick")# properly aggregated, but not accounting for age distributionbad_alembic_dt <- alembic(  ifr_levin,  within(age_pyramid, weight <- c(rep(1, 101), 0)), age_limits, 0:101)ifr_unif <- blend(bad_alembic_dt)lines(  age_limits, c(ifr_unif$value, tail(ifr_unif$value, 1)),  type = "s", col = "darkgreen")

Distill Outcomes

Description

distill takes a low-age resolution outcome, for example deaths,and proportionally distributes that outcome into a higher age resolution foruse in subsequent analyses like years-life-lost style calculations.

Usage

distill(alembic_dt, outcomes_dt, groupcol = names(outcomes_dt)[1])

Arguments

alembic_dt

analembic() return value

outcomes_dt

a long-formatdata.frame with a column either namedfrom ormodel_from and a columnvalue (other columns will be silentlyignored)

groupcol

a string, the name of the outcome model group column. Theoutcomes_dt[[groupcol]] column must match themodel_partition lowerbounds, as provided when constructing thealembic_dt withalembic().

Details

When thevalue column is re-calculated, note that it will aggregate allrows with matchinggroupcol entries inoutcomes_dt. If you need to groupby other features in your input data (e.g. if you need to distill outcomesacross multiple simulation outputs or at multiple time points), that has tobe done by external grouping then callingdistill().

Value

adata.frame, withoutput_partition and recalculatedvalue column

Examples

ifr_levin <- function(age_in_years) {  (10^(-3.27 + 0.0524 * age_in_years))/100}age_limits <- c(seq(0, 69, by = 5), 70, 80, 101)age_pyramid <- data.frame(  from = 0:101, weight = ifelse(0:101 < 65, 1, .99^(0:101-64)))age_pyramid$weight[102] <- 0# flat age distribution, then 1% annual deaths, no one lives past 101alembic_dt <- alembic(ifr_levin, age_pyramid, age_limits, 0:101)results <- data.frame(model_partition = head(age_limits, -1))results$value <- 10distill(alembic_dt, results)

Distillation Calculation Comparison Summary

Description

Implements several approaches to imputing higher resolution outcomes, thentables them up for convenient plotting.

Usage

distill_summary(alembic_dt, outcomes_dt, groupcol = names(outcomes_dt)[1])

Arguments

alembic_dt

analembic() return value

outcomes_dt

a long-formatdata.frame with a column either namedfrom ormodel_from and a columnvalue (other columns will be silentlyignored)

groupcol

a string, the name of the outcome model group column. Theoutcomes_dt[[groupcol]] column must match themodel_partition lowerbounds, as provided when constructing thealembic_dt withalembic().

Value

adata.table, columns:

Examples

library(data.table)f_param <- function(age_in_years) {  (10^(-3.27 + 0.0524 * age_in_years))/100}model_partition <- c(0, 5, 20, 65, 101)density_dt <- data.table(  from = 0:101, weight = c(rep(1, 66), exp(-0.075 * 1:35), 0))alembic_dt <- alembic(  f_param, density_dt, model_partition, seq(0, 101, by = 1L))# for simplicity, assume a uniform force-of-infection across ages =># infections proportion to population density.model_outcomes_dt <- density_dt[from != max(from), .(value = sum(f_param(from) * weight)),  by = .(model_from = model_partition[findInterval(from, model_partition)])]ds_dt <- distill_summary(alembic_dt, model_outcomes_dt)

Interpolation Options

Description

Creates and interpolation options object for use withalembic().

Usage

interpolate_opts(fun, kind = c("point", "integral"), ...)

Arguments

fun

a function

kind

a string; either "point" or "integral". How to interpret thex, y values being interpolated. Either as point observations of a function ORas the integral of the function over the interval.

...

arbitrary other arguments, but checked against signature offun

Details

This method creates the interpolation object for use withalembic(); thisis a convenience method, which does basic validation on arguments and ensuresthe information used inalembic() to do interpolation is available.

The... arguments will be provided tofun when it is invoked tointerpolate the tabular "functional" form of arguments toalembic(). Iffun has an argumentkind, that parameter will also be passed wheninvoking the function; if not, then the input data will be transformed to\{x, z\} pairs, such thatx_{i+1}-x_{i} * z_i = y_i - i.e., transforming toa point value and a functional form which is assumed constant until the nextpartition.

Value

a list, withfun andkind keys, as well as whatever other validkeys appear in....

Examples

interpolate_opts(  fun = stats::splinefun, method = "natural", kind = "point")interpolate_opts(  fun = stats::approxfun, method = "constant", yleft = 0, yright = 0,  kind = "integral")

Create a Least-Common-Interval Partition

Description

Internal utility method for creating partitions, possibly from multipledistinct partitions. Validates inputs.

Usage

make_partition(model_partition = numeric(0), output_partition = numeric(0))

Arguments

model_partition

the model partition

output_partition

the output partition

Value

a sorted numeric vector with unique values


Compose Parameter & Density Functions

Description

Purely internal, called afterto_function, so no direct user arguments.#'

Usage

make_weight(f_param, f_pop)

Arguments

f_param

a function; the parameter function, varying with the aggregate

f_pop

a function; the density function, varying with the aggregate

Value

a new function, f(x) = f_param(x)*f_pop(x)


Parameter Calculation Comparison Summary

Description

Implements several approaches to computing partition-aggregated parameters,then tables them up for convenient plotting.

Usage

parameter_summary(f_param, f_pop, model_partition, resolution = 101L)

Arguments

f_param

a function,f(x) which transforms the feature (e.g. age),to yield the parameter values. Alternatively, adata.frame where the firstcolumn is the feature and the second is the parameter; seexy.coords() fordetails. If the latter, combined withpars_interp_opts to create aparameter function.

f_pop

likef_param, either a density function (though it doesnot have to integrate to 1 like a pdf) or adata.frame of values. If thelatter, it is treated as a series of populations within intervals, andthen interpolated withpop_interp_opts to create a density function.

model_partition

a numeric vector of cut points, which define thepartitioning that will be used in the model; must be length > 1

resolution

the number of points to calculate for the underlyingf_param function. The default 101 points means 100 partitions.

Value

adata.table, columns:

Examples

# COVID IFR from Levin et al 2020 https://doi.org/10.1007/s10654-020-00698-1f_param <- function(age_in_years) {  (10^(-3.27 + 0.0524 * age_in_years))/100}densities <- data.frame(  from = 0:101,  weight = c(rep(1, 66), exp(-0.075 * 1:35), 0))model_partition <- c(0, 5, 20, 65, 101)ps_dt <- parameter_summary(f_param, densities, model_partition)ps_dtggplot(ps_dt) + aes(x, y = value, color = method) +  geom_line(data = function(dt) subset(dt, method == "f_val")) +  geom_step(data = function(dt) subset(dt, method != "f_val")) +  theme_bw() + theme(    legend.position = "inside", legend.position.inside = c(0.05, 0.95),    legend.justification = c(0, 1)  ) + scale_color_discrete(    "Method", labels = c(      f_val = "f(x)", f_mid = "f(mid(x))", f_mean = "f(E[x])",      mean_f = "discrete E[f(x)]", wm_f = "integrated E[f(x)]"    )  ) +  scale_x_continuous("Age", breaks = seq(0, 100, by = 10)) +  scale_y_log10("IFR", breaks = 10^c(-6, -4, -2, 0), limits = 10^c(-6, 0))

Internal Conversion of Data to Function

Description

Internal Conversion of Data to Function

Usage

to_function(x, bounds, interp_opts)

Arguments

x

a function or the single argument version ofx inxy.coords() (as perapproxfun() orsplinefun() inputs). Pass throughfrom user input, must be checked

bounds

numeric vector, length 2: the partition lower bound; not checked,result ofrange(make_partition(...)).

interp_opts

ifx is function, ignored. Otherwise,an interpolating function and its arguments.

Value

a function


[8]ページ先頭

©2009-2025 Movatter.jp