Learn R Programming

⚠️There's a newer version (0.1.7) of this package.Take me there.

expirest

The package supports shelf life estimation for chemically derived medicines, either following the standard method proposed by the International Council for Harmonisation (ICH), in quality guideline Q1E Evaluation of Stability Data or following the worst-case scenario consideration (what-if analysis) described in the Australian Regulatory Guidelines for Prescription Medicines (ARGPM), guidance on Stability testing for prescription medicines.

Installation

A stable version of expirest can be installed from CRAN:

# install.packages("expirest")

The development version is available from GitHub by:

# install.packages("devtools")
devtools::install_github("piusdahinden/expirest")

Examples

Example 1

This is a basic example which shows you how to solve a common problem using a data set containing the moisture stability data (% (w/w)) of three batches obtained over a 24 months period of a drug product. A total of n = 33 independent measurements are available (corresponding to data shown in Table XIII in LeBlond et al. (2011).

library(expirest)

# Data frame
str(exp3)
#> 'data.frame':    33 obs. of  3 variables:
#>  $ Batch   : Factor w/ 3 levels "b1","b2","b3": 1 1 1 1 1 1 1 1 1 1 ...
#>  $ Month   : num  0 1 2 3 3 6 6 12 12 24 ...
#>  $ Moisture: num  2.2 1.7 3.32 2.76 2.43 ...

# Perform what-if shelf life estimation (wisle) and print a summary
res1 <- expirest_wisle(
      data = exp3, response_vbl = "Moisture", time_vbl = "Month",
      batch_vbl = "Batch", rl = 3.00, rl_sf = 3, sl = c(0.5, 4.5),
      sl_sf = c(1, 2), srch_range = c(0, 500), alpha = 0.05,
      alpha_pool = 0.25, xform = c("no", "no"), shift = c(0, 0),
      sf_option = "tight", ivl = "confidence", ivl_type = "one.sided",
      ivl_side = "upper")

class(res1)
#> [1] "expirest_wisle"
summary(res1)
#> 
#> Summary of shelf life estimation following the ARGPM
#>   guidance "Stability testing for prescription medicines"
#> 
#> The best model accepted at a significance level of 0.25 has
#>  Common intercepts and Common slopes (acronym: cics).
#> 
#> Worst case intercept and batch:
#>   RL Batch Intercept
#> 1  3    NA  2.456782
#> 
#> Estimated shelf lives for the cics model:
#>    SL RL    wisle     osle
#> 1 4.5  3 72.50545 96.30552
#> 
#> Abbreviations:
#>   ARGPM: Australian Regulatory Guidelines for Prescription Medicines;
#>   ICH: International Council for Harmonisation;
#>   osle: Ordinary shelf life estimation (i.e. following the ICH guidance);
#>   RL: Release Limit;
#>   SL: Specification Limit;
#>   wisle: What-if (approach for) shelf life estimation (see ARGPM guidance).

# Prepare graphical representation
ggres1 <- plot_expirest_wisle(
      model = res1, rl_index = 1, response_vbl_unit = "% (w/w)",
      x_range = NULL, y_range = c(0.2, 5.2), scenario = "standard",
      mtbs = "verified", plot_option = "full", ci_app = "ribbon")
class(ggres1)
#> [1] "plot_expirest_wisle"
plot(ggres1)

Example 2

The model type in Example 1 was common intercept / common slope (cics). The model type in this example is different intercept / different slope (dids). A data set containing the potency stability data (in % of label claim (LC)) of five batches of a drug product obtained over a 24 months period is used. A total of n = 53 independent measurements are available (corresponding to data shown in Tables IV, VI and VIII in LeBlond et al. (2011).

# Data frame
str(exp1)
#> 'data.frame':    53 obs. of  3 variables:
#>  $ Batch  : Factor w/ 6 levels "b2","b3","b4",..: 1 1 1 1 1 1 1 1 1 1 ...
#>  $ Month  : num  0 1 3 3 6 6 12 12 24 24 ...
#>  $ Potency: num  101 101.3 99.8 99.2 99.5 ...

# Perform what-if shelf life estimation (wisle) and print a summary
res2_1 <- expirest_wisle(
      data = exp1[exp1$Batch %in% c("b4", "b5", "b8"), ],
      response_vbl = "Potency", time_vbl = "Month", batch_vbl = "Batch",
      rl = c(98.0, 98.5, 99.0), rl_sf = rep(2, 3), sl = 95, sl_sf = 2,
      srch_range = c(0, 500), alpha = 0.05, alpha_pool = 0.25,
      xform = c("no", "no"), shift = c(0, 0), sf_option = "tight",
      ivl = "confidence", ivl_type = "one.sided", ivl_side = "lower")

summary(res2_1)
#> 
#> Summary of shelf life estimation following the ARGPM
#>   guidance "Stability testing for prescription medicines"
#> 
#> The best model accepted at a significance level of 0.25 has
#>  Different intercepts and Different slopes (acronym: dids).
#> 
#> Worst case intercepts and batches:
#>     RL Batch Intercept
#> 1 98.0    b8  101.2594
#> 2 98.5    b8  101.2594
#> 3 99.0    b8  101.2594
#> 
#> Estimated shelf lives for the dids model (for information, the results of
#>   the model fitted with pooled mean square error (pmse) are also shown:
#>   SL   RL     wisle wisle (pmse)     osle osle (pmse)
#> 1 95 98.0  7.619661     7.483223 15.84487     15.6061
#> 2 95 98.5  8.997036     8.858223 15.84487     15.6061
#> 3 95 99.0 10.303030    11.344407 15.84487     15.6061
#> 
#> Abbreviations:
#>   ARGPM: Australian Regulatory Guidelines for Prescription Medicines;
#>   ICH: International Council for Harmonisation;
#>   osle: Ordinary shelf life estimation (i.e. following the ICH guidance);
#>   pmse: Pooled mean square error;
#>   RL: Release Limit;
#>   SL: Specification Limit;
#>   wisle: What-if (approach for) shelf life estimation (see ARGPM guidance).

# Prepare graphical representation
ggres2_1 <- plot_expirest_wisle(
      model = res2_1, rl_index = 2, response_vbl_unit = "%", x_range = NULL,
      y_range = c(93, 107), scenario = "standard", mtbs = "verified",
      plot_option = "full", ci_app = "ribbon")
class(ggres2_1)
#> [1] "plot_expirest_wisle"
plot(ggres2_1)

Note that if the model type is dids, then by default the results are plotted that are obtained by fitting individual regression lines to each batch. To get a plot of the dids model with pooled mean square error (pmse) instead, use the setting mtbs = "dids.pmse".

# Prepare graphical representation of the dids.pmse model
ggres2_2 <- plot_expirest_wisle(
      model = res2_1, rl_index = 2, response_vbl_unit = "%", x_range = NULL,
      y_range = c(93, 107), scenario = "standard", mtbs = "dids.pmse",
      plot_option = "full", ci_app = "ribbon")
plot(ggres2_2)

The examples above were performed with three batches. The assessment can be performed with any numbers of batches, even with just one batch. If the assessment is performed with a single batch, the results are reported as dids model while the results for all other models are NA. As an example, the following example was performed with batch b4.

# Perform what-if shelf life estimation (wisle) and print a summary
res2_2 <- expirest_wisle(
      data = exp1[exp1$Batch == "b4", ],
      response_vbl = "Potency", time_vbl = "Month", batch_vbl = "Batch",
      rl = c(98.0, 98.5, 99.0), rl_sf = rep(2, 3), sl = 95, sl_sf = 2,
      srch_range = c(0, 500), alpha = 0.05, alpha_pool = 0.25,
      xform = c("no", "no"), shift = c(0, 0), sf_option = "tight",
      ivl = "confidence", ivl_type = "one.sided", ivl_side = "lower")

summary(res2_2)
#> 
#> Summary of shelf life estimation following the ARGPM
#>   guidance "Stability testing for prescription medicines"
#> 
#> The best model accepted at a significance level of 0.25 has
#>  NA intercepts and NA slopes (acronym: n.a.).
#> 
#> Worst case intercepts and batches:
#>     RL Batch Intercept
#> 1 98.0    b4  104.0706
#> 2 98.5    b4  104.0706
#> 3 99.0    b4  104.0706
#> 
#> Estimated shelf lives for the n.a. model (for information, the results of
#>   the model fitted with pooled mean square error (pmse) are also shown:
#>   SL   RL    wisle wisle (pmse)     osle osle (pmse)
#> 1 95 98.0 13.72633           NA 40.79176          NA
#> 2 95 98.5 16.09778           NA 40.79176          NA
#> 3 95 99.0 18.40465           NA 40.79176          NA
#> 
#> Abbreviations:
#>   ARGPM: Australian Regulatory Guidelines for Prescription Medicines;
#>   ICH: International Council for Harmonisation;
#>   osle: Ordinary shelf life estimation (i.e. following the ICH guidance);
#>   pmse: Pooled mean square error;
#>   RL: Release Limit;
#>   SL: Specification Limit;
#>   wisle: What-if (approach for) shelf life estimation (see ARGPM guidance).

# Prepare graphical representation
ggres2_2 <- plot_expirest_wisle(
      model = res2_2, rl_index = 2, response_vbl_unit = "%", x_range = NULL,
      y_range = c(93, 107), scenario = "standard", mtbs = "verified",
      plot_option = "full", ci_app = "ribbon")
plot(ggres2_2)

Example 3

The assessments in Example 1 and Example 2 were made with the option sf_option = "tight". The parameter sf_option affects the shelf life (sl) and release limits (rl). The setting sf_option = "tight" means that of the sl and rl limits only the number of significant digits specified by the parameters rl_sf and sl_sf, respectively, are taken into account. If sf_option = "loose", then the limits are widened, i.e. four on the order of the last significant digit + 1 is added if ivl_side = "upper" or five on the order of the last significant digit + 1 is subtracted if ivl_side = "lower". For illustration, the following example reproduces Example 2 with the option sf_option = "loose".

# Perform what-if shelf life estimation (wisle) and print a summary
res3 <- expirest_wisle(
      data = exp1[exp1$Batch %in% c("b4", "b5", "b8"), ],
      response_vbl = "Potency", time_vbl = "Month", batch_vbl = "Batch",
      rl = c(98.0, 98.5, 99.0), rl_sf = rep(3, 3), sl = 95, sl_sf = 2,
      srch_range = c(0, 500), alpha = 0.05, alpha_pool = 0.25,
      xform = c("no", "no"), shift = c(0, 0), sf_option = "loose",
      ivl = "confidence", ivl_type = "one.sided", ivl_side = "lower")

summary(res3)
#> 
#> Summary of shelf life estimation following the ARGPM
#>   guidance "Stability testing for prescription medicines"
#> 
#> The best model accepted at a significance level of 0.25 has
#>  Different intercepts and Different slopes (acronym: dids).
#> 
#> Worst case intercepts and batches:
#>     RL Batch Intercept
#> 1 98.0    b8  101.2594
#> 2 98.5    b8  101.2594
#> 3 99.0    b8  101.2594
#> 
#> Estimated shelf lives for the dids model (for information, the results of
#>   the model fitted with pooled mean square error (pmse) are also shown:
#>   SL   RL     wisle wisle (pmse)    osle osle (pmse)
#> 1 95 98.0  8.863085     8.724968 17.0387    16.77679
#> 2 95 98.5 10.174754    11.221221 17.0387    16.77679
#> 3 95 99.0 11.440468    11.276686 17.0387    16.77679
#> 
#> Abbreviations:
#>   ARGPM: Australian Regulatory Guidelines for Prescription Medicines;
#>   ICH: International Council for Harmonisation;
#>   osle: Ordinary shelf life estimation (i.e. following the ICH guidance);
#>   pmse: Pooled mean square error;
#>   RL: Release Limit;
#>   SL: Specification Limit;
#>   wisle: What-if (approach for) shelf life estimation (see ARGPM guidance).

# Prepare graphical representation
ggres3 <- plot_expirest_wisle(
      model = res3, rl_index = 2, response_vbl_unit = "%", x_range = NULL,
      y_range = c(93, 107), scenario = "standard", mtbs = "verified",
      plot_option = "full", ci_app = "ribbon")
plot(ggres3)

Literature

LeBlond, D., Griffith, D. and Aubuchon, K. Linear Regression 102: Stability Shelf Life Estimation Using Analysis of Covariance. J Valid Technol (2011) 17(3): 47-68.

Contact

Pius Dahinden, Tillotts Pharma AG


Copy Link

Version

Install

install.packages('expirest')

Monthly Downloads

306

Version

0.1.6

License

GPL (>= 2)

Issues

Pull Requests

Stars

Forks

Maintainer

Pius Dahinden

Last Published

March 25th, 2024

Functions in expirest (0.1.6)

extract_wc_x

Extract worst case x value
expirest_osle

Ordinary shelf life estimation (osle)
exp1

Stability potency data of five batches
compile_wisle_summary

Compile “what-if shelf life estimation” (wisle) assessment results
get_n_whole_part

Get number of digits of whole part (of a decimal number)
get_icpt_list

List of intercepts
get_intvl_limit

Confidence or prediction interval limit
get_n_list_levels

Determine the level of nesting of a list
get_arrow

Prepare arrow supporting the explanation of graphical elements
get_model_list

Linear model fitting
get_distance

Determine distance of lines
find_poi

Find the point of intersection (POI)
get_hlines

Prepare horizontal lines
get_icpt

Getting the intercept(s) of a linear model
get_text_annotation

Prepare text annotation
get_variable_list

Listing of variable names
get_wcs_limit

Determination of the “worst case scenario” (wcs) limit
get_segments

Prepare segments explaining graphical elements
get_vlines

Prepare vertical lines
get_predictions

Get the predicted values
get_poi_list

List of points of intersection
get_wc_icpt

Get intercepts of the worst case batches
get_osle_poi_list

Compile information on worst case batches for ordinary shelf life estimation
get_relevant_limits

Get relevant limits
get_wisle_poi_list

Compile information on worst case batches for what-if shelf life estimation
print.expirest_wisle

Print a summary of the what-if shelf life estimation (wisle)
print.expirest_osle

Print a summary of the shelf life estimation (osle)
print.plot_expirest_osle

Print a plot illustrating the shelf life estimation (osle)
plot_expirest_osle

Illustrating the ordinary shelf life estimate (osle)
plot.plot_expirest_osle

Plot illustrating the shelf life estimation (osle)
plot.plot_expirest_wisle

Plot illustrating the what-if shelf life estimation (wisle)
plot_expirest_wisle

Illustrating the what-if (approach for) shelf life estimate (wisle)
get_xformed_variables

Transformation of variables
print.plot_expirest_wisle

Print a plot illustrating the what-if shelf life estimation (wisle)
try_get_model

Try getting results from expression
summary.expirest_osle

Summary of the shelf life estimation (osle)
summary.expirest_wisle

Summary of the what-if shelf life estimation (wisle)
set_limits

Adjustment of limits
print_val

Print value(s)
exp2

Stability related substance data of three batches
extract_from_ll_wcsl

Extract information from “worst case scenario” (wcs) limit lists list
expirest_wisle

What-if (approach for) shelf life estimation (wisle)
check_ancova

Result of ANCOVA model check
exp3

Stability moisture data of three batches
exp4

Stability data of 4 batches