mztia {disprofas}R Documentation

Martinez & Zhao Tolerance Interval Approach

Description

The Martinez & Zhao Tolerance Interval Approach (mztia) is a simple approach for the comparison of dissolution profiles. The mztia() function calculates tolerance intervals (\textit{TI}) at each time point of the dissolution profiles of a set of reference batches. By aid of a graphical display the test batches are checked to lie within the \textit{TI} boundaries or within certain limits exceeding the \textit{TI} boundaries by a specified percentage.

Usage

mztia(
  data,
  shape,
  tcol,
  grouping,
  reference,
  response = NULL,
  na_rm = FALSE,
  alpha = 0.05,
  pp = 0.99,
  cap = TRUE,
  bounds = c(0, 100),
  qs = c(5, 15),
  ...
)

Arguments

data

A data frame with the dissolution profile data in wide or in long format (see parameter shape). If the data frame is in wide format, it is tried to extract the information on the time points of dissolution testing from the column names of the columns specified by the tcol parameter. Thus, they must contain extractable numeric information, e.g., (t_0, t_5, t_10). If the data frame is in long format, it must have a column of time points (column specified via the tcol parameter).

shape

A character string that indicates whether the data frame is in long or in wide format.

tcol

If shape is "wide" an integer vector of indices, if shape is "long" an integer that specifies the column(s) containing the profile time points. If the data frame is in wide format it is reshaped using the function reshape() from the ‘stats’ package.

grouping

A character string that specifies the column in data that contains the group names (i.e. a factorial variable, e.g., for the differentiation of batches or formulations of a drug product).

reference

A character string that specifies the name of the reference group from the grouping variable.

response

A character string that is expected if data is provided in long format to specify the column with the % drug release values. The default is NULL.

na_rm

A logical value that indicates whether observations containing NA (or NaN) values should be removed (na_rm = TRUE) or not (na_rm = FALSE). The default is na_rm = FALSE.

alpha

A numeric value between 0 and 1 that specifies the probability level. The default is 0.05.

pp

A numeric value between 0 and 1 that specifies the proportion of the population being enclosed by the tolerance interval boundaries. The default is 0.99.

cap

A logical variable that indicates whether the calculated tolerance limits should be limited (i.e. capped). The default is TRUE.

bounds

A numeric vector of the form c(lower, upper) that specifies the “lower” and “upper” limits, respectively, for the % drug release at which the calculated tolerance interval limits should be capped (see parameter cap. This parameter is only relevant if cap = TRUE. The default is c(0, 100).

qs

A numeric vector of the form c(Q S1, Q S2) that specifies the allowable deviations from the specifications in percent according to the S1 and S2 acceptance criteria of USP chapter <711> on dissolution. The default is c(5, 15).

...

Further arguments passed on to the reshape() from the ‘stats’ package.

Details

The tolerance interval approach proposed by Martinez & Zhao (2018) is a simple approach for the comparison of dissolution profiles. The authors propose to calculate for each time point of a set of reference dissolution profiles a tolerance interval (\textit{TI}), i.e. intervals containing pp% of the population of potential values for reference product at a probability level of alpha / 2 per tail (i.e., (1 - alpha) 100% confidence). Based on these \textit{TI}s the dissolution profiles of the test batch(es) is (are) compared, i.e. the corresponding data points should lie within the \textit{TI}s. The \textit{TI}s are calculated as

Y_{utl,ltl} = \bar{Y} \pm k \times s

where \bar{Y} is the average, s is the sample standard deviation, and the factor k is calculated according to Hahn (Hahn & Meeker (1991)), as proposed in Martinez & Zhao (2018).

Since the goal of the comparison is not to confirm simply “statistical sameness” but “product comparability”, Martinez & Zhao propose allowing acceptable deviations by utilizing the concepts described by the United States Pharmacopoeia (USP), chapter <711> on dissolution, defining allowable deviations from a set of product specifications (Q). The \textit{TI}s serve as the target value Q at each sampling time. The allowable deviations about Q are defined by the S1 and S2 acceptance criteria of USP chapter <711> on dissolution:

  1. The S1 level boundary is defined by Q \pm 5% at each time point. For every 12 profiles tested, only one profile is allowed to exceed the S1 bounds.

  2. The S2 level boundary is defined by Q \pm 15% at each time point. No observation from any of the test dissolution profiles is allowed to exceed the S2 bounds.

In situations where the reference formulation itself has more than one of twelve observations (profiles) exceeding S1 at one or more time points, additional runs of the reference product must be performed. It is deemed appropriate to use the same values of S1 and S2 across all time points because the high variability associated with the early sampling times is already factored into the \textit{TI}s.

\textit{TI} calculation according to Hahn is proposed because it appeared to be more numerically stable and gave more consistent \textit{TI}s than the \textit{TI} calculation method proposed by Howe (Howe 1969) when samples were very variable. The reason might be due to the less stringent requirements imposed by Hahn's method with respect to the normality of the data.

Value

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

Variables

A list of the variables and the corresponding values.

Limits

A data frame of the limits calculated for each time point.

Data

A data frame consisting of the provided data, complemented by the calculated tolerance interval results.

Profile.TP

If shape is "wide" a named numeric vector of the columns in data specified by tcol. Given that the column names contain extractable numeric information, e.g., the testing time points of the dissolution profile, it contains the corresponding numeric values. Elements where no numeric information could be extracted are NA. If shape is "long" it is a numeric value that specifies the column containing the % release values.

References

Martinez, M.N., and Zhao, X. A simple approach for comparing the in vitro dissolution profiles of highly variable drug products: a proposal. AAPS Journal. 2018; 20: 78.
doi:10.1208/s12248-018-0238-1

Howe, W.G. Two-sided tolerance limits for normal populations - some improvements. J Am Stat Assoc. 1969; 64: 610-620.
doi:10.1080/01621459.1969.10500999

Hahn, G.J., and Meeker, W. Q. Statistical intervals: A guide for practitioners. (1991); John Wiley & Sons, New York. Hahn's method is also described in: SAS/QC 13.1: User's Guide. Chapter 5, sub-chapter “Details: INTERVALS Statement”, pp 421-424. SAS Institute Inc. 2013. Cary, NC.
https://support.sas.com/documentation/cdl/en/qcug/66857/PDF/default/qcug.pdf

U.S. Pharmacopoeia. 2016 U.S. Pharmacopoeia-National Formulary (USP 39 NF 34). Volume 1. Rockville, Md: United States Pharmacopeial Convention, Inc; 2015. <711> Dissolution.

See Also

bootstrap_f2, mimcr.

Examples

# Calculation of tolerance intervals
m_alpha_P <- matrix(c(rep(c(0.01, 0.05, 0.1), each = 3),
                      1 - rep(c(0.1, 0.05, 0.01), times = 3)),
                    ncol = 2, byrow = FALSE)

ll <-
  apply(m_alpha_P, MARGIN = 1, FUN = function(x)
    mztia(data = dip5, shape = "long", tcol = 1, grouping = "type",
          reference = "reference", response = "weight", na_rm = FALSE,
          alpha = x[1], P = x[2], cap = FALSE)[["Data"]][102, "weight"])
ul <-
  apply(m_alpha_P, MARGIN = 1, FUN = function(x)
    mztia(data = dip5, shape = "long", tcol = 1, grouping = "type",
          reference = "reference", response = "weight", na_rm = FALSE,
          alpha = x[1], P = x[2], cap = FALSE)[["Data"]][103, "weight"])

# Expected results in ll and ul
rbind(ll, ul)
#        [,1]    [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]
# ll 11.91648 11.8987 11.86395 11.92132 11.90446 11.87152 11.92373 11.90734
# ul 12.10212 12.1199 12.15465 12.09728 12.11414 12.14708 12.09487 12.11126
#       [,9]
# ll 11.8753
# ul 12.1433

# Use a data frame in wide format
# Using the defaults; Limits are capped to the range specified by 'bounds'
res1 <- mztia(data = dip1, shape = "wide", tcol = 3:10, grouping = "type",
              reference = "R")
res1$Limits

# Expected results in res1$Limits
# Time     Mean      LTL       UTL   S1.LTL    S1.UTL   S2.LTL    S2.UTL
# 1    5 46.77167 27.22641  66.31693 22.22641  71.31693 12.22641  81.31693
# 2   10 60.13333 46.15483  74.11184 41.15483  79.11184 31.15483  89.11184
# 3   15 67.27500 56.90417  77.64583 51.90417  82.64583 41.90417  92.64583
# 4   20 71.98667 65.44354  78.52979 60.44354  83.52979 50.44354  93.52979
# 5   30 78.07000 69.54259  86.59741 64.54259  91.59741 54.54259 101.59741
# 6   60 84.81667 77.20275  92.43058 72.20275  97.43058 62.20275 107.43058
# 7   90 89.09333 76.24588 100.00000 71.24588 105.00000 61.24588 115.00000
# 8  120 91.43833 80.29321 100.00000 75.29321 105.00000 65.29321 115.00000

# Without capping of limits to 105%
res2 <- mztia(data = dip1, shape = "wide", tcol = 3:10, grouping = "type",
              reference = "R", cap = FALSE)
res2$Limits

# Expected results in res1$Limits
# Time     Mean      LTL       UTL   S1.LTL    S1.UTL   S2.LTL    S2.UTL
# 1    5 46.77167 27.22641  66.31693 22.22641  71.31693 12.22641  81.31693
# 2   10 60.13333 46.15483  74.11184 41.15483  79.11184 31.15483  89.11184
# 3   15 67.27500 56.90417  77.64583 51.90417  82.64583 41.90417  92.64583
# 4   20 71.98667 65.44354  78.52979 60.44354  83.52979 50.44354  93.52979
# 5   30 78.07000 69.54259  86.59741 64.54259  91.59741 54.54259 101.59741
# 6   60 84.81667 77.20275  92.43058 72.20275  97.43058 62.20275 107.43058
# 7   90 89.09333 76.24588 101.94079 71.24588 106.94079 61.24588 116.94079
# 8  120 91.43833 80.29321 102.58346 75.29321 107.58346 65.29321 117.58346

# Tolerance intervals are calculated exclusively for the level of the
# grouping variable that is specified by the reference variable. Therefore,
# the following code produces the same limits summary as in res2$Limits.
tmp <- rbind(dip1,
             data.frame(type = "T2",
                        tablet = as.factor(1:6),
                        dip1[7:12, 3:10]))

res2 <- mztia(data = dip1, shape = "wide", tcol = 3:10, grouping = "type",
              reference = "R", cap = FALSE)
res3 <- mztia(data = tmp, shape = "wide", tcol = 3:10, grouping = "type",
              reference = "R", cap = FALSE)

isTRUE(all.equal(res2$Limits, res3$Limits))
# [1] TRUE

[Package disprofas version 0.2.0 Index]