expirest_osle {expirest}R Documentation

Ordinary shelf life estimation (osle)

Description

Based on a linear regression model fitted to a stability data set the function expirest_osle() estimates the shelf life, or retest period, following the ICH Q1E guideline. The abbreviation “osle” stands for “ordinary shelf life estimation”.

Usage

expirest_osle(
  data,
  response_vbl,
  time_vbl,
  batch_vbl,
  sl,
  sl_sf,
  srch_range,
  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",
  ...
)

Arguments

data

A data frame with the columns specified by response_vbl, time_vbl and batch_vbl.

response_vbl

A character string that specifies the response variable name that must be a column of data.

time_vbl

A character string that specifies the time variable name that must be a column of data.

batch_vbl

A character string that specifies the column in data with the grouping information (i.e. a factorial variable) for the differentiation of the observations of the various batches.

sl

A numeric value or a numeric vector of length 2 that specifies the specification limit or limits. If a vector is provided it must be of the form c(lower limit, upper limit).

sl_sf

A positive integer or a vector of positive integers that specifies the number of “significant figures” (sf) of sl. It must have the same length as sl.

srch_range

A vector of length 2 that specifies the end-points of the (time) range that is supposed to contain the shelf life or retest period.

alpha

A numeric value between 0 and 1 that specifies the significance level for the calculation of confidence or prediction intervals. The default is 0.05.

alpha_pool

A numeric value between 0 and 1 that specifies the type I error rate for the test of the poolability of the batches. The default is 0.25, following ICH Q1E guideline. The value should not be changed unless supported by well-founded reasons.

xform

A vector of two character strings that specifies the transformation of the response and the time variable. The default is “no” transformation, i.e. c("no", "no"), where the first element specifies the transformation of the x variable and the second element the transformation of the y variable. Valid alternatives for x and/or y variable transformation are "log" (natural logarithm), "sqrt" (square root) and "sq" (square).

shift

A vector of two values which will be added to the variables x and/or y before they are transformed as specified by the xform parameter, where the first element will be added to the x variable and the second element to the y variable. The purpose is to prevent an undefined state which could arise when variables with values of \leq 0 are log or square root transformed. The default is c(0, 0).

sf_option

A character string that specifies if the limits (rl or sl) should be regarded as “tight” or “loose”, i.e. either "tight" or "loose", respectively. The default is "tight". The option "tight" means that the limits are rounded to the number of significant digits specified by the parameters rl_sf and sl_sf. If sf_option = "loose", 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 = "upper".

ivl

A character string of either "confidence" or "prediction" that specifies the type of interval of interest. The default is "confidence".

ivl_type

A character string that specifies if a “one sided” or a “two sided” interval should be calculated, i.e. either "one.sided" or "two.sided", respectively. The default is "one.sided".

ivl_side

A character string that specifies if the specification limit, given that the limit has only one side, is an “upper” or a “lower” bound, i.e. it is specified as either "upper" or "lower", respectively. The default is "lower". If the specification has two boundaries, then this parameter specifies the preferred side. If no side is preferred over the other, "both" can be used.

...

Additional named or unnamed arguments passed on to uniroot().

Details

According to ICH Q1E guideline, “an appropriate approach to retest period or shelf life estimation is to analyse a quantitative attribute by determining the earliest time at which the 95 percent confidence limit for the mean intersects the proposed acceptance criterion” (in this package, this point is called the “point of intersection” (POI)). Furthermore, it says that “for an attribute known to increase with time, the upper one-sided 95 percent confidence limit should be compared to the acceptance criterion. For an attribute that can either increase or decrease, or whose direction of change is not known, two-sided 95 percent confidence limits should be calculated and compared to the upper and lower acceptance criteria.” The approach can be used to estimate the retest period or shelf life for a single batch or for multiple batches. According to the guideline, “for a drug substance or for a drug product available in a single strength and a single container size and/or fill, the retest period or shelf life is generally estimated based on the stability data from a minimum of three batches.

Before performing the retest period or shelf life estimation with results from multiple batches, the most suitable model should be determined. It should particularly be verified if data of all test batches are poolable or not. Details on this are described in section “Checking batch poolability” below.

Value

An object of class ‘expirest_osle’ is returned, containing the following elements:

Data

Data frame of the original data including new columns with transformed variables, if applicable.

Parameters

A list of the parameters with the elements alpha, alpha.pool, ivl, ivl.type and ivl.side.

Variables

A list of the variable names, i.e. the original names of batch_vbl, time_vbl and response_vbl and, if applicable, of the transformed variables.

Model.Type

A list of two elements that specifies which model, based on the ANCOVA analysis, suits best. The first element (type.spec) is a numeric vector of length 2 that specifies the best model accepted at the significance level specified by alpha.pool. The first number represents the decision on the intercept and the second on the slope, where 1 stands for “common” and 2 stands for “different”. The second element (type.acronym) is an acronym representing the first item.

Models

A list of four elements named cics, dics, dids.pmse and dids. The first three elements contain the ‘lm’ objects of the “common intercept / common slope” (cics), “different intercept / common slope” (dics) and “different intercept / different slope” (dids) models. The fourth element is a list of the ‘lm’ objects that is obtained from fitting a regression model to the data of each level of the categorical variable separately. The cics, dics and dids.pmse elements are NA if data of only a single batch is available.

AIC

A numeric named vector of the Akaike Information Criterion (AIC) values of the cics, dics and dids.pmse models.

BIC

A numeric named vector of the Bayesian Information Criterion (BIC) values of each of the cics, dics and dids.pmse models.

wc.icpt

A numeric named vector of the worst case intercepts. The information about which limit the corresponding confidence interval crosses is stored in the attribute named side.

wc.batch

A numeric named vector of the batches with the worst case intercepts. The information about which limit the corresponding confidence interval crosses is stored in the attribute named side.

Limits

A list of all limits.

Intercepts

A list of the intercepts of all models.

All.POI

A list of two elements named lower and upper that contain either NA or lists of the POI values of all models.

POI

A numeric named vector of the POI values of the worst case batches of each model. The information about which limit the corresponding confidence interval crosses is stored in the attribute named side.

Checking batch poolability

According to ICH Q1E guideline, construction of the 95% confidence interval on the basis of the combined data of all test batches is allowed only if it has been confirmed by aid of a statistical test whether the regression lines from the different batches have a common slope and a common intercept. A significance level of alpha_pool = 0.25 should to be used for both batch-related terms, and the test of the slopes has to precede the test of the intercepts. From these tests, three possible models may be appropriate, i.e.

The common intercept / different slope model is not of practical relevance because the corresponding model is missing an effect. If the slopes are significantly different, there is no point comparing intercepts. The dids model has individual intercepts and individual slopes, and the calculation of confidence intervals is based on the corresponding individual mean square errors. The different intercept / different slope model where the mean square error is pooled across batches is reported as dids.pmse.

These requirements can be checked by aid of an “ANalysis of COVAriance” (ANCOVA) including the batch variable as main effect and as batch \times time interaction term. The full ANCOVA model simultaneously tests all the effects, and non-significant effects can be identified and removed for fitting of the final regression model that is used for the estimation of the shelf life or retest period.

The significance level (alpha_pool = 0.25, Type I error) is used to increase the power of the test to detect cases where the data should not be pooled. Setting alpha_pool = 0.25 decreases the probability of incorrectly concluding that stability data from multiple batches can be pooled. On the other hand, though, it increases the probability of using a single batch to determine expiry when pooling batches would be more appropriate.

References

International Council for Harmonisation of Technical Requirements for Registration of Pharmaceuticals for Human (ICH), Harmonised Tripartite Guideline, Evaluation of Stability Data Q1E, step 4, February 2003 (CPMP/ICH/420/02).

See Also

expirest_wisle, uniroot, lm, AIC, BIC.

Examples

# Successful estimations
# A model with common intercepts / common slopes (cics)
res1 <-
  expirest_osle(data = exp1[exp1$Batch %in% c("b2", "b5", "b7"), ],
                response_vbl = "Potency", time_vbl = "Month",
                batch_vbl = "Batch", sl = 95, sl_sf = 3,
                srch_range = c(0, 500), sf_option = "loose")
res1$Model.Type
res1$POI

# Expected results in res1$Model.Type
# $type.spec
# common.icpt  common.slp
#           1           1
#
# $type.acronym
# [1] "cics"

# Expected results in res1$POI
#     cics      dics dids.pmse      dids
# 26.22410  24.80030  23.66724  23.34184
# attr(,"side")
#     cics      dics dids.pmse      dids
#  "lower"   "lower"   "lower"   "lower"

# The parameter settings sf_option = "loose" and ivl_side = "lower" (the
# default setting of ivl_side) cause the specification limit of 95.0
# (sl_sf = 3, i.e. 3 significant digits) to be reduced by 0.05, i.e. the
# actual specification limit is 94.95.

# A model with different intercepts / different slopes (dids)
res2 <-
  expirest_osle(data = exp1[exp1$Batch %in% c("b4", "b5", "b8"), ],
                response_vbl = "Potency", time_vbl = "Month",
                batch_vbl = "Batch", sl = 95, sl_sf = 3,
                srch_range = c(0, 500), sf_option = "loose")
res2$Model.Type
res2$POI

# Expected results in res2$Model.Type
# $type.spec
# common.icpt  common.slp
#           0           0
#
# $type.acronym
# [1] "dids"

# Expected results in res2$POI
#     cics      dics dids.pmse      dids
# 28.12518  22.47939  15.72348  15.96453
# attr(,"side")
#     cics      dics dids.pmse      dids
#  "lower"   "lower"   "lower"   "lower"

# Estimation where it is not know a priori which limit is crossed first, i.e.
# letting the estimation be done for both specification limits.
res3 <-
  expirest_osle(
    data = exp3, response_vbl = "Moisture", time_vbl = "Month",
    batch_vbl = "Batch", sl = c(1.5, 3.5), sl_sf = c(2, 2),
    srch_range = c(0, 500), sf_option = "loose", ivl = "confidence",
    ivl_type = "two.sided", ivl_side = "both")
res3$Model.Type
res3$POI

# Expected results in res3$Model.Type
# $type.spec
# common.icpt  common.slp
#           1           1
#
# $type.acronym
# [1] "cics"

# Expected results in res3$POI
#     cics      dics dids.pmse      dids
# 46.85172  41.84802  22.41808  22.50966
# attr(,"side")
#     cics      dics dids.pmse      dids
#  "upper"   "upper"   "upper"   "lower"

# The parameter settings sf_option = "loose" and ivl_side = "both" (the
# default setting of ivl_side) cause the specification limits of 1.5 and 3.5
# (sl_sf = 2, i.e. 2 significant digits) to be reduced by 0.05 and increased
# by 0.04, respectively, i.e. the actual specification limits are 1.45 and
# 3.54, respectively.

# Analysis with a single batch
res4 <-
  expirest_osle(
    data = exp3[exp3$Batch == "b1", ], response_vbl = "Moisture",
    time_vbl = "Month", batch_vbl = "Batch", sl = c(1.5, 3.5),
    sl_sf = c(2, 2), srch_range = c(0, 500), sf_option = "tight",
    ivl = "confidence", ivl_type = "two.sided", ivl_side = "both")

# Since only one batch is involved there is no model type. Nevertheless, the
# result is reported under the dids model name.
res4$Model.Type
res4$POI

# Expected results in res4$Model.Type
# $type.spec
# common.icpt  common.slp
#         NA           NA
#
# $type.acronym
# [1] "n.a."

# Expected results in res4$POI
# cics      dics dids.pmse      dids
#   NA        NA        NA  21.42596
# attr(,"side")
# cics      dics dids.pmse      dids
# "NA"      "NA"      "NA"   "lower"

# Unsuccessful estimations
## Not run: 
  # Intervals are wider than the specification limits (no intersection).
  res5 <-
    expirest_osle(
      data = exp3, response_vbl = "Moisture", time_vbl = "Month",
      batch_vbl = "Batch", sl = 1.5, sl_sf = 2, srch_range = c(0, 500),
      sf_option = "tight", ivl = "prediction", ivl_type = "two.sided",
      ivl_side = "lower")
  res5$POI

  # (Expected) results in res5$POI
  #    cics      dics dids.pmse      dids
  #     NA        NA        NA        NA
  # attr(,"side")
  #    cics      dics dids.pmse      dids
  # "lower"   "lower"   "lower"   "lower"

  # Estimation may also fail because of an inappropriate 'srch_range' setting.
  res6 <-
    expirest_osle(data = exp1[exp1$Batch %in% c("b2", "b5", "b7"), ],
                  response_vbl = "Potency", time_vbl = "Month",
                  batch_vbl = "Batch", sl = 95, sl_sf = 3,
                  srch_range = c(0, 5))
  res6$POI

  # (Expected) results in res6$POI
  #    cics      dics dids.pmse      dids
  #     NA        NA        NA        NA
  # attr(,"side")
  #    cics      dics dids.pmse      dids
  # "lower"   "lower"   "lower"   "lower"

## End(Not run)

[Package expirest version 0.1.6 Index]