Bioequivalence Docstrings

Bioequivalence.EMA_CMAXConstant
EMA_CMAX = [GeometricMeanRatioBounds(), AverageBioequivalenceWithExpandingLimits(0.76, CV_min = 0.3, CV_max = 0.5)]

Criteria for the European Medicines Agency average bioequivalence for Cmax endpoints.

Bioequivalence.EMA_NarrowTherapeuticIndexConstant
EMA_NarrowTherapeuticIndex = [AverageBioequivalenceWithExpandingLimits(0, lower_bound = 0.9, upper_bound = 1.11)]

Criteria for the European Medicines Agency narrow therapeutic index drugs.

Bioequivalence.FDAConstant
FDA = [GeometricMeanRatioBounds(), AverageBioequivalenceWithExpandingLimits((log(1.25) / 0.25)^2)]

Criteria for the U.S. Food and Drug Administration (non-narrow therapeutic index drugs):

If the within subject variability of the reference formulation is less than 30%, the unscaled confidence interval should pass the standard critertia: LB ≥ 80% ^ UB ≤ 125%. Otherwise, the 95% upper confidence bound for (T̄ₜ - Ȳᵣ)² - 𝜃 * σwᵣ² ≤ 0 (numbers should be kept to a minimum of four significant figures for comparison) with 𝜃 ≈ 0.7967 and 80% ≤ GMR ≤ 125%.

Bioequivalence.FDA_NarrowTherapeuticIndexConstant
FDA_NarrowTherapeuticIndex = [
    AverageBioequivalenceWithExpandingLimits(0),
    AverageBioequivalenceWithExpandingLimits((log(1 / 0.9) / 0.1)^2, CV_min = 0, CV_max = 0.2142),
    WithinSubjectVariabilityRatio()
    ]

Criteria for the U.S. Food and Drug Administration Narrow Therapeutic Index drug:

a) The 95% upper confidence bound for (T̄ₜ - Ȳᵣ)² - 𝜃 * σwᵣ² ≤ 0 (numbers should be kept to a minimum of four significant figures for comparison). 𝜃 ≈ 1.11.

b) Regular unscaled bioequivalence limits of [80.00%, 125.00%] should be passed.

c) The proposed requirement for the upper limit of the 90% equal-tails confidence interval for σwₜ / σwᵣ ≤ 2.5.

Bioequivalence.AverageBioequivalenceWithExpandingLimitsType
AverageBioequivalenceWithExpandingLimits(
    θ::Real = -1;
    CV_min::Real = 0.3,
    CV_max::Real = Inf,
    lower_bound::Real = 0.8,
    upper_bound::Real = 1.25
    )

Criteria for the average bioequivalence acceptable bounds. If θ < 0, use the θ from the BioequivalenceEndpointOutput if available. If θ > 0, overwrite BioequivalenceEndpointOutput parameters in assessment. If θ == 0, use unscaled confidence interval with specified interval.

See also assess_be

Bioequivalence.BioequivalenceEndpointOutputType
BioequivalenceEndpointOutput

A bioequivalence study output object.

See also: pumas_be.

Fields

  • endpoint_name the name of the endpoint
  • data::DataFrame data used for the study
  • design::NamedTuple number of subjects in each sequence
  • model statistical models used for the analysis
  • model_stats statistics for the model
  • stat_tests p-values
  • result::DataFrame results for inference in a Dataframe format
  • result_table::OrderedDict{Symbol,Any} results in an OrderedDict format
  • input_parameters a copy of the input parameters used

Examples

julia> data = dataset(joinpath("bioequivalence", "RST_RTS_SRT_STR_TRS_TSR", "PJ2017_4_5"))
186×5 DataFrame
 Row │ id     sequence  period  AUC      Cmax
     │ Int64  String3   Int64   Int64?   Int64?
─────┼───────────────────────────────────────────
   1 │     1  SRT            1     7260     1633
   2 │     1  SRT            2     6463     1366
   3 │     1  SRT            3     8759     2141
   4 │     2  RTS            1     3457      776
   5 │     2  RTS            2     6556     2387
   6 │     2  RTS            3     4081     1355
   7 │     4  TSR            1     4006     1326
   8 │     4  TSR            2     4879     1028
   9 │     4  TSR            3     3817     1052
  10 │     5  STR            1     4250      945
  11 │     5  STR            2     3487     1041
  ⋮  │   ⋮       ⋮        ⋮        ⋮        ⋮
 177 │    61  RTS            3     3779     1144
 178 │    62  SRT            1     5787     1461
 179 │    62  SRT            2     7069     1995
 180 │    62  SRT            3     6530     1236
 181 │    63  TRS            1     2204      495
 182 │    63  TRS            2     2927      770
 183 │    63  TRS            3  missing  missing
 184 │    67  RST            1     4045     1025
 185 │    67  RST            2     7865     2668
 186 │    67  RST            3  missing  missing
                                 165 rows omitted

julia> output = pumas_be(data, endpoint = :Cmax)

sequence ╲ period │  1   2   3
──────────────────┼───────────
RST               │  9   9   8
RTS               │ 11  11  11
SRT               │ 11  11  11
STR               │ 10  10  10
TRS               │ 11  11  10
TSR               │ 10  10  10

-----------------------------------------------------------------------------------------
Paradigm: 3 formulations
Model: Linear model
Criteria: Standard ABE
Endpoint: Cmax
Formulations: Reference(R), Test(S and T)
-----------------------------------------------------------------------------------------
                                             Results(Cmax)    Assessment   Criteria      
-----------------------------------------------------------------------------------------
S             Geometric Mean S/R Ratio (%)   159.4                                       
              Degrees of Freedom             118                                         
              90% Confidence Interval (%)    [146.1, 173.9]   Fail         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
T             Geometric Mean T/R Ratio (%)   129.9                                       
              Degrees of Freedom             118                                         
              90% Confidence Interval (%)    [119.1, 141.8]   Fail         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
Variability   CV (%) | σ̂                     29.69 | 0.2907                              
-----------------------------------------------------------------------------------------

julia> output.model
StatsModels.TableRegressionModel{GLM.LinearModel{GLM.LmResp{Vector{Float64}}, GLM.DensePredChol{Float64, LinearAlgebra.CholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}}}, Matrix{Float64}}

endpoint ~ 1 + sequence + formulation + period + sequence & id_within_sequence

Coefficients:
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
                                             Coef.   Std. Error       t  Pr(>|t|)     Lower 95%      Upper 95%
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
(Intercept)                              6.62478      0.0712859   92.93    <1e-99    6.48361       6.76595
sequence: RTS                            0.063206     0.0766071    0.83    0.4110   -0.0884968     0.214909
sequence: SRT                            0.154313     0.0766071    2.01    0.0462    0.00260986    0.306016
sequence: STR                           -0.157545     0.0782601   -2.01    0.0464   -0.312522     -0.00256894
sequence: TRS                            0.139309     0.0773718    1.80    0.0743   -0.0139084     0.292526
sequence: TSR                            0.0515892    0.0782601    0.66    0.5111   -0.103387      0.206566
formulation: S                           0.466225     0.0525563    8.87    <1e-14    0.362149      0.570301
formulation: T                           0.261828     0.0525354    4.98    <1e-05    0.157794      0.365862
period: 2                                0.108264     0.0522307    2.07    0.0404    0.00483251    0.211695
period: 3                                0.065041     0.0528643    1.23    0.2210   -0.0396448     0.169727
sequence: RST & id_within_sequence: 2   -0.3262       0.15878     -2.05    0.0421   -0.640626     -0.0117729
sequence: RTS & id_within_sequence: 2    0.331286     0.16         2.07    0.0406    0.0144416     0.64813
sequence: SRT & id_within_sequence: 2   -0.501131     0.16        -3.13    0.0022   -0.817975     -0.184287
sequence: STR & id_within_sequence: 2    0.0716688    0.159198     0.45    0.6534   -0.243587      0.386925
sequence: TRS & id_within_sequence: 2    0.301479     0.160375     1.88    0.0626   -0.0161081     0.619065
sequence: TSR & id_within_sequence: 2    0.102741     0.159198     0.65    0.5199   -0.212515      0.417997
sequence: RST & id_within_sequence: 3   -0.51875      0.15878     -3.27    0.0014   -0.833177     -0.204324
sequence: RTS & id_within_sequence: 3    0.0552092    0.16         0.35    0.7307   -0.261635      0.372053
sequence: SRT & id_within_sequence: 3   -0.507347     0.16        -3.17    0.0019   -0.824191     -0.190502
sequence: STR & id_within_sequence: 3    0.170922     0.159198     1.07    0.2852   -0.144334      0.486178
sequence: TRS & id_within_sequence: 3    0.433913     0.160375     2.71    0.0078    0.116326      0.7515
sequence: TSR & id_within_sequence: 3    0.28292      0.159198     1.78    0.0781   -0.0323359     0.598176
sequence: RST & id_within_sequence: 4   -0.223057     0.15878     -1.40    0.1627   -0.537483      0.0913701
sequence: RTS & id_within_sequence: 4    0.733329     0.16         4.58    <1e-04    0.416485      1.05017
sequence: SRT & id_within_sequence: 4   -0.271254     0.16        -1.70    0.0926   -0.588098      0.0455901
sequence: STR & id_within_sequence: 4   -0.314543     0.159198    -1.98    0.0505   -0.629799      0.00071311
sequence: TRS & id_within_sequence: 4   -0.0758404    0.160375    -0.47    0.6372   -0.393427      0.241746
sequence: TSR & id_within_sequence: 4   -0.696306     0.159198    -4.37    <1e-04   -1.01156      -0.38105
sequence: RST & id_within_sequence: 5    0.0929178    0.15878      0.59    0.5595   -0.221509      0.407344
sequence: RTS & id_within_sequence: 5   -0.396815     0.16        -2.48    0.0145   -0.713659     -0.0799707
sequence: SRT & id_within_sequence: 5    0.590422     0.16         3.69    0.0003    0.273578      0.907266
sequence: STR & id_within_sequence: 5   -0.358415     0.159198    -2.25    0.0262   -0.673671     -0.0431591
sequence: TRS & id_within_sequence: 5    0.275196     0.160375     1.72    0.0888   -0.0423908     0.592783
sequence: TSR & id_within_sequence: 5   -0.31622      0.159198    -1.99    0.0493   -0.631476     -0.000964371
sequence: RST & id_within_sequence: 6   -0.33796      0.15878     -2.13    0.0354   -0.652387     -0.0235336
sequence: RTS & id_within_sequence: 6    0.0150445    0.16         0.09    0.9252   -0.3018        0.331889
sequence: SRT & id_within_sequence: 6   -0.150983     0.16        -0.94    0.3473   -0.467827      0.165862
sequence: STR & id_within_sequence: 6   -0.155991     0.159198    -0.98    0.3292   -0.471246      0.159265
sequence: TRS & id_within_sequence: 6   -0.043903     0.160375    -0.27    0.7848   -0.36149       0.273684
sequence: TSR & id_within_sequence: 6    0.604415     0.159198     3.80    0.0002    0.289159      0.919671
sequence: RST & id_within_sequence: 7   -0.0104784    0.15878     -0.07    0.9475   -0.324905      0.303948
sequence: RTS & id_within_sequence: 7   -0.73212      0.16        -4.58    <1e-04   -1.04896      -0.415276
sequence: SRT & id_within_sequence: 7    0.431845     0.16         2.70    0.0080    0.115001      0.748689
sequence: STR & id_within_sequence: 7   -0.0893864    0.159198    -0.56    0.5755   -0.404642      0.22587
sequence: TRS & id_within_sequence: 7    0.0591428    0.160375     0.37    0.7130   -0.258444      0.376729
sequence: TSR & id_within_sequence: 7   -0.93299      0.159198    -5.86    <1e-07   -1.24825      -0.617734
sequence: RST & id_within_sequence: 8    0.558771     0.15878      3.52    0.0006    0.244345      0.873198
sequence: RTS & id_within_sequence: 8   -0.1594       0.16        -1.00    0.3212   -0.476244      0.157444
sequence: SRT & id_within_sequence: 8   -0.316077     0.16        -1.98    0.0505   -0.632921      0.000767652
sequence: STR & id_within_sequence: 8    0.377635     0.159198     2.37    0.0193    0.0623787     0.692891
sequence: TRS & id_within_sequence: 8   -0.500216     0.160375    -3.12    0.0023   -0.817802     -0.182629
sequence: TSR & id_within_sequence: 8    0.246161     0.159198     1.55    0.1247   -0.0690946     0.561417
sequence: RST & id_within_sequence: 9    0.498742     0.191139     2.61    0.0102    0.120235      0.87725
sequence: RTS & id_within_sequence: 9   -0.0536409    0.16        -0.34    0.7380   -0.370485      0.263203
sequence: SRT & id_within_sequence: 9    0.173038     0.16         1.08    0.2817   -0.143807      0.489882
sequence: STR & id_within_sequence: 9   -0.330719     0.159198    -2.08    0.0399   -0.645975     -0.0154627
sequence: TRS & id_within_sequence: 9    0.409442     0.160375     2.55    0.0120    0.0918552     0.727029
sequence: TSR & id_within_sequence: 9    0.386147     0.159198     2.43    0.0168    0.0708915     0.701403
sequence: RST & id_within_sequence: 10   0.0        NaN          NaN       NaN     NaN           NaN
sequence: RTS & id_within_sequence: 10   0.262141     0.16         1.64    0.1040   -0.0547029     0.578985
sequence: SRT & id_within_sequence: 10  -0.0533425    0.16        -0.33    0.7394   -0.370187      0.263502
sequence: STR & id_within_sequence: 10   0.573641     0.159198     3.60    0.0005    0.258385      0.888897
sequence: TRS & id_within_sequence: 10  -0.343073     0.160375    -2.14    0.0345   -0.66066      -0.0254862
sequence: TSR & id_within_sequence: 10   0.272039     0.159198     1.71    0.0901   -0.0432167     0.587295
sequence: RST & id_within_sequence: 11   0.0        NaN          NaN       NaN     NaN           NaN
sequence: RTS & id_within_sequence: 11  -0.281096     0.16        -1.76    0.0815   -0.59794       0.035748
sequence: SRT & id_within_sequence: 11   0.255426     0.16         1.60    0.1131   -0.0614185     0.57227
sequence: STR & id_within_sequence: 11   0.0        NaN          NaN       NaN     NaN           NaN
sequence: TRS & id_within_sequence: 11  -0.52366      0.19394     -2.70    0.0080   -0.907714     -0.139606
sequence: TSR & id_within_sequence: 11   0.0        NaN          NaN       NaN     NaN           NaN
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Bioequivalence.GeometricMeanRatioBoundsType
GeometricMeanRatioBounds(lower_bound::Real = 0.8, upper_bound::Real = 1.25)

Criteria for the point estimate. Checks that the geometric mean ratio (GMR) lies within the accepted range.

Bioequivalence.ReferenceScaledAverageBioequivalanceType
ReferenceScaledAverageBioequivalance(
    data::AbstractDataFrame,
    𝜃::Real,
    σwᵣ::Real = -1;
    k::Union{Real, Missing} = -1,
    level::Real = 0.9,
    level_y::Real = 0.95,
    userepeatedobsonly::Bool = true
    ) -> ReferenceScaledAverageBioequivalance

Reference-scaled average bioequivalence.

Arguments

  • data::AbstractDataFrame: dataset adhering to the schema from preprocess_be.
  • 𝜃::Real: parameter for reference-scaling.
  • σwᵣ::Real: estimate for the within-subject variability. If negative, the function will compute it.
  • k::Real: degrees of freedom of the within-subject variability. If negative, the function will compute it.
  • level::Real: confidence level for the confidence interval.
  • level_y::Real: confidence level for the upper bound of (Ȳₜ - Ȳᵣ)² - 𝜃 * σwᵣ².
  • userepeatedobsonly: controls the behavior of within_subject_variability if used to estimate σwᵣ and k.

See also preprocess_be and within_subject_variability

Reference

Food and Drug Administration (2021). Bioequivalence Studies With Pharmacokinetic Endpoints for Drugs Submitted Under an ANDA Guidance for Industry. https://www.fda.gov/media/87219/download.

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "SLTGSF2020_DS16"));

julia> pkdata = preprocess_be(data, endpoint = :PK);

julia> rsabe = ReferenceScaledAverageBioequivalance(pkdata, 0.76)
Critical boundary: -0.0416
Regulatory parameter: 0.76
95.0% upper confidence bound with 36.0 degrees of freedom
Bioequivalence.WithinSubjectVariabilityRatioType
WithinSubjectVariabilityRatio(upper_bound::Real = 2.5)

Requirement for the upper limit of the 90% equal-tails confidence interval for within-subject variability test/reference ratio is less than or equal to the upper limit.

Bioequivalence.assess_beFunction
assess_be(
    criterion::BioequivalenceCriterion,
    endpoint_output::BioequivalenceEndpointOutput
) -> BioequivalenceEndpointDecision
assess_be(
    criteria::AbstractVector{<:BioequivalenceCriterion},
    endpoint_output::BioequivalenceEndpointOutput
) -> BioequivalenceEndpointDecision

Return a BioequivalenceEndpointDecision struct which includes properties crtieria for a vector of criterion. The result of the assessment is accessible through the assessments property which is a BitMatrix. The rows refer to a formulation comparison (e.g., R|T) and the columns whether the criterion was passed or not.

Bioequivalence.assess_beMethod
assess_be(criteria::AbstractVector{<:BioequivalenceCriterion}, endpoint_output::BioequivalenceEndpointOutput)

Return the average bioequivalence conclusions based on the specified criteria.

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "SLTGSF2020_DS16"))
152×4 DataFrame
 Row │ id     sequence  period  PK
     │ Int64  String7   Int64   Float64
─────┼──────────────────────────────────
   1 │     1  RTTR           1   0.2813
   2 │     1  RTTR           2   0.2947
   3 │     1  RTTR           3   0.5471
   4 │     1  RTTR           4   0.651
   5 │     2  RTTR           1   0.2024
   6 │     2  RTTR           2   0.1782
   7 │     2  RTTR           3   0.2076
   8 │     2  RTTR           4   0.3604
   9 │     3  TRRT           1   0.4332
  10 │     3  TRRT           2   0.3131
  11 │     3  TRRT           3   0.2132
  ⋮  │   ⋮       ⋮        ⋮        ⋮
 143 │    38  RTTR           3   2.6522
 144 │    38  RTTR           4   1.2808
 145 │    39  RTTR           1   0.3847
 146 │    39  RTTR           2   0.2991
 147 │    39  RTTR           3   0.3353
 148 │    39  RTTR           4   0.3483
 149 │    40  RTTR           1   1.0289
 150 │    40  RTTR           2   0.753
 151 │    40  RTTR           3   0.7894
 152 │    40  RTTR           4   0.6129
                        131 rows omitted

julia> output = pumas_be(data, endpoint = :PK)

sequence ╲ period │  1   2   3   4
──────────────────┼───────────────
RTTR              │ 20  20  20  20
TRRT              │ 18  18  18  18

-----------------------------------------------------------------------------------------
Paradigm: Replicated crossover that supports reference scaling
Model: Mixed model (unequal variance)
Criteria: Standard ABE
Endpoint: PK
Formulations: Reference(R), Test(T)
-----------------------------------------------------------------------------------------
                                             Results(PK)      Assessment   Criteria
-----------------------------------------------------------------------------------------
T             Geometric Mean T/R Ratio (%)   78.83
              Degrees of Freedom             86.57
              90% Confidence Interval (%)    [69.31, 89.66]   Fail         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
Variability   CVᵣ (%) | σ̂ᵣ                   49.72 | 0.47
              CVₜ (%) | σ̂ₜ                   51.41 | 0.4843
              Variability Ratio (%)          103.1
-----------------------------------------------------------------------------------------
ANOVA         Treatment (p-value)            0.00283
              Sequence (p-value)             0.5266
              Period (p-value)               0.03876
-----------------------------------------------------------------------------------------

julia> assess_be(StandardBioequivalenceCriterion, output)
Formulation: T - R -- Fail
  LB ≥ 0.8% ^ UB ≤ 1.25% -- Fail

julia> assess_be(FDA, output)
Formulation: T - R -- Fail
  0.8 ≤ GMR ≤ 1.25 -- Fail
  Reference Scaled Average Bioequivalance w/ 𝜃: 0.796689, CV_min: 0.3, CV_max: Inf -- Pass

julia> assess_be(FDA_NarrowTherapeuticIndex, output)
Formulation: T - R -- Fail
  LB ≥ 0.8% ^ UB ≤ 1.25% -- Fail
  Reference Scaled Average Bioequivalance w/ 𝜃: 1.110084, CV_min: 0.0, CV_max: 0.2142 -- Fail
  Upper bound of the within-subject variability ratio ≤ 2.5 -- Pass
Bioequivalence.detect_designFunction
detect_design(sequences::AbstractVector) ->
    NamedTuple{(:design, :replicated, :crossover), Tuple{String, ReplicationType, Bool}}
detect_design(
    data::AbstractDataFrame,
    sequence::Union{AbstractString, Symbol} = :sequence
    ) -> NamedTuple{(:design, :replicated, :supports_rsabe, :crossover), Tuple{String, ReplicationType, Bool, Bool}}

Return a named tuple which describes the design. The fields are:

  • :design - a String describing the design.
  • :replicated - a value of ReplicationType.
  • :supports_rsabe - true if RSABE is supported with this design.
  • :crossover - true if a crossover design.
Bioequivalence.generate_designMethod
generate_design(
    sequences::AbstractVector{<:AbstractString},
    amt::Union{Number,AbstractVector{<:Number}},
    subjects_per_sequence::Union{<:Integer,AbstractVector{<:Integer}},
    ) -> DataFrame

Returns a DataFrame with id, sequence, period, amt, evid, cmt, and time. It can be used to quickly set up data for Pumas, NCA, and Bioequivalence. In order to add covariates, use innerjoin to join the result of this function with another DataFrame with covariates.

Examples

julia> skeleton = generate_design(["RT", "TR"], [0, 50], 10)
40×8 DataFrame
 Row │ id     sequence  period  formulation  amt    time   evid   cmt
     │ Int64  Cat…      Int64   Char         Int64  Int64  Int64  Int64
─────┼──────────────────────────────────────────────────────────────────
   1 │     1  RT             1  R                0      0      4      1
   2 │     1  RT             2  T               50      0      4      1
   3 │     2  RT             1  R                0      0      4      1
   4 │     2  RT             2  T               50      0      4      1
   5 │     3  RT             1  R                0      0      4      1
   6 │     3  RT             2  T               50      0      4      1
   7 │     4  RT             1  R                0      0      4      1
   8 │     4  RT             2  T               50      0      4      1
   9 │     5  RT             1  R                0      0      4      1
  10 │     5  RT             2  T               50      0      4      1
  11 │     6  RT             1  R                0      0      4      1
  ⋮  │   ⋮       ⋮        ⋮          ⋮         ⋮      ⋮      ⋮      ⋮
  31 │    16  TR             1  T               50      0      4      1
  32 │    16  TR             2  R                0      0      4      1
  33 │    17  TR             1  T               50      0      4      1
  34 │    17  TR             2  R                0      0      4      1
  35 │    18  TR             1  T               50      0      4      1
  36 │    18  TR             2  R                0      0      4      1
  37 │    19  TR             1  T               50      0      4      1
  38 │    19  TR             2  R                0      0      4      1
  39 │    20  TR             1  T               50      0      4      1
  40 │    20  TR             2  R                0      0      4      1
                                                         19 rows omitted

julia> skeleton = generate_design(["RTRT", "TRTR"], [50, 75], [12, 10])
88×8 DataFrame
 Row │ id     sequence  period  formulation  amt    time   evid   cmt
     │ Int64  Cat…      Int64   Char         Int64  Int64  Int64  Int64
─────┼──────────────────────────────────────────────────────────────────
   1 │     1  RTRT           1  R               50      0      4      1
   2 │     1  RTRT           2  T               75      0      4      1
   3 │     1  RTRT           3  R               50      0      4      1
   4 │     1  RTRT           4  T               75      0      4      1
   5 │     2  RTRT           1  R               50      0      4      1
   6 │     2  RTRT           2  T               75      0      4      1
   7 │     2  RTRT           3  R               50      0      4      1
   8 │     2  RTRT           4  T               75      0      4      1
   9 │     3  RTRT           1  R               50      0      4      1
  10 │     3  RTRT           2  T               75      0      4      1
  11 │     3  RTRT           3  R               50      0      4      1
  ⋮  │   ⋮       ⋮        ⋮          ⋮         ⋮      ⋮      ⋮      ⋮
  79 │    20  TRTR           3  T               75      0      4      1
  80 │    20  TRTR           4  R               50      0      4      1
  81 │    21  TRTR           1  T               75      0      4      1
  82 │    21  TRTR           2  R               50      0      4      1
  83 │    21  TRTR           3  T               75      0      4      1
  84 │    21  TRTR           4  R               50      0      4      1
  85 │    22  TRTR           1  T               75      0      4      1
  86 │    22  TRTR           2  R               50      0      4      1
  87 │    22  TRTR           3  T               75      0      4      1
  88 │    22  TRTR           4  R               50      0      4      1
                                                         67 rows omitted
Bioequivalence.geocv2sigmaMethod
geocv2sigma(CV::Union{Real,Missing}) = √(log(1 + CV^2))

Transform the the coefficient of variation (CV) to the σ parameter of a log-normal distribution.

Examples

julia> geocv2sigma(0.30)
0.29356037920852396
Bioequivalence.inference_model_typeMethod
inference_model_type(be_output::BioequivalenceEndpointOutput)::InferenceModelType

Determines the inference model type used in a bioequivalence study for an endpoint.

Bioequivalence.is_preprocessedMethod
is_preprocessed(data::AbstractDataFrame)

Returns true if data is suspected of having the form returned by preprocess_be.

Bioequivalence.legacy_showMethod
legacy_show(obj::BioequivalenceEndpointOutput)

This can be used to present output of pumas_be in legacy mode, presenting a dataframe obj.result in place of tabular output (out.result_table).

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "PJ2017_4_3"));

julia> legacy_show(pumas_be(data))
sequence ╲ period │ 1  2  3  4
──────────────────┼───────────
RTTR              │ 8  8  8  8
TRRT              │ 9  9  9  8

Reference scaled using 𝜃 = 0.797

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
             δ       SE       lnLB     lnUB    GMR      LB     UB      CVᵣ     CVₜ  σ_ratio     σ⁺        cb    dof
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
T - R  0.03568  0.02431  -0.006884  0.07826  1.036  0.9931  1.082  0.08022  0.1084     1.35  2.118  0.001813  15.25
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Bioequivalence.preprocess_beMethod
preprocess_be(
    data::AbstractDataFrame,
    id::Union{AbstractString, Symbol} = :id,
    sequence::Union{AbstractString, Symbol} = :sequence,
    period::Union{AbstractString, Symbol} = :period,
    endpoint::Union{AbstractString, Symbol} = :AUC,
    logtransformed::Bool = false
    ) -> DataFrame

Return the standardized dataset with id, sequence, period, formulation, and endpoint. The standardized dataset:

  • selects only relevant variables
  • applies the natural log transformation to the endpoint if in natural scale
  • renames variables to their canonical name for the functions
  • drops missing observations
  • computes the formulation based on the sequence and period variables
  • converts the variables into the appropiate format for analysis (e.g., factors)

The sequence/formulation take values RT, RST, or ABCD based on alphabetical order and number of formulations.

Examples

julia> data = dataset(joinpath("bioequivalence", "RT_TR", "SLF2014_1"))
36×4 DataFrame
 Row │ id     sequence  period  AUC
     │ Int64  String3   Int64   Float64
─────┼──────────────────────────────────
   1 │     1  RT             1   181.09
   2 │     1  RT             2   210.14
   3 │     2  RT             1   114.48
   4 │     2  RT             2    98.72
   5 │     3  TR             1   225.95
   6 │     3  TR             2   241.09
   7 │     4  RT             1   176.91
   8 │     4  RT             2   186.65
   9 │     5  TR             1   147.01
  10 │     5  TR             2   139.56
  11 │     6  TR             1    97.53
  ⋮  │   ⋮       ⋮        ⋮        ⋮
  27 │    14  TR             1   179.96
  28 │    14  TR             2   181.09
  29 │    15  TR             1   173.86
  30 │    15  TR             2   206.66
  31 │    16  RT             1   144.0
  32 │    16  RT             2   143.25
  33 │    17  RT             1   185.1
  34 │    17  RT             2   192.22
  35 │    18  TR             1   117.99
  36 │    18  TR             2   125.5
                         15 rows omitted

julia> preprocess_be(data)
36×6 DataFrame
 Row │ id    id_within_sequence  sequence  period  formulation  endpoint
     │ Cat…  Cat…                Cat…      Cat…    Cat…         Float64
─────┼───────────────────────────────────────────────────────────────────
   1 │ 1     1                   RT        1       R             5.19899
   2 │ 1     1                   RT        2       T             5.34777
   3 │ 2     2                   RT        1       R             4.7404
   4 │ 2     2                   RT        2       T             4.59229
   5 │ 3     1                   TR        1       T             5.42031
   6 │ 3     1                   TR        2       R             5.48517
   7 │ 4     3                   RT        1       R             5.17564
   8 │ 4     3                   RT        2       T             5.22924
   9 │ 5     2                   TR        1       T             4.9905
  10 │ 5     2                   TR        2       R             4.93849
  11 │ 6     3                   TR        1       T             4.58016
  ⋮  │  ⋮            ⋮              ⋮        ⋮          ⋮          ⋮
  27 │ 14    7                   TR        1       T             5.19273
  28 │ 14    7                   TR        2       R             5.19899
  29 │ 15    8                   TR        1       T             5.15825
  30 │ 15    8                   TR        2       R             5.33107
  31 │ 16    8                   RT        1       R             4.96981
  32 │ 16    8                   RT        2       T             4.96459
  33 │ 17    9                   RT        1       R             5.2209
  34 │ 17    9                   RT        2       T             5.25864
  35 │ 18    9                   TR        1       T             4.7706
  36 │ 18    9                   TR        2       R             4.83231
                                                          15 rows omitted
Bioequivalence.pumas_beFunction
pumas_be(
    data::AbstractDataFrame,
    criteria::AbstractVector{<:BioequivalenceCriterion} = StandardBioequivalenceCriterion;
    endpoint::Union{AbstractString,Symbol} = "AUC",
    logtransformed::Bool = false,
    reference_scale::Union{Real,Nothing} = nothing,
    cv_max::Real = Inf,
    id::Union{AbstractString,Symbol} = "id",
    sequence::Union{AbstractString,Symbol} = "sequence",
    period::Union{AbstractString,Symbol} = "period",
    nonparametric::Bool = occursin(r"(?i)tmax", string(endpoint)),
    homogeneity::Union{Bool, Nothing} = nothing,
    userepeatedobsonly::Bool = true,
    reml::Bool = true,
    level::Real = 0.9,
    alpha::Real = 0.1,
    level_y::Real = 0.95,
    sigdigits::Integer = 4,
    ) -> BioequivalenceEndpointOutput

BioequivalenceEndpointOutput constructor. See also: BioequivalenceEndpointOutput, preprocess_be, and run_be.

Arguments

  • data: must have id, sequence, period, and an endpoint.
  • criteria: by default this argument can be left blank. Yet if it specified, assess_be will use a different assessment. Use NoAssessmentBioequivalenceCriterion if wishing not to assess.
  • endpoint: which variable is the endpoint?
  • logtransformed: has the endpoint been log transformed?
  • id: which variable is the subject identifier?
  • sequence: which variable is the sequence?
  • period: which variable is the period?
  • nonparametric: whether to use a nonparametric (default if endpoint includes tmax ignoring case) or parametric model.
  • homogeneity: whether formulation groups should be modeled with equal variance
  • userepeatedobsonly: whether estimating the within subject variability should only repeated observations
  • reference_scale: 𝜃 for reference scale (e.g., FDA ≈ 0.797, FDA/NTI ≈ 1.11, EMA = 0.76). If nothing (default) then values set based on criteria.
  • cv_max: maximum within subject variability for reference scaling (FDA = Inf, FDA/NTI = 0.2142, EMA = 0.5). If reference_scale is nothing then value adjusted based on criteria.
  • reml: whether the linear mixed model should use restricted maximum likelihood or maximum likelihood
  • level: applies to the confidence intervals for the GMR
  • alpha: applies to the upper bound of the within subject variability ratio
  • level_y: applies to the critical boundary for reference-scaled average bioequivalence
  • sigdigits: results given with how many significant digits.

Current designs include: nonparametric, parallel, and various crossover designs | Description | Treatments | Periods | Sequences | Replicated | Crossover | |–––––––––––––-|––––––|––––-|–––––-|––––––|–––––-| | R_T | 2 | 1 | 2 | No | No | | RT_TR | 2 | 2 | 2 | No | Yes | | RR_RT_TR_TT | 2 | 2 | 4 | No | Yes | | RTR_TRT | 2 | 3 | 2 | Fully | Yes | | RTR_TRR | 2 | 3 | 2 | Partially | Yes | | RTT_TRR | 2 | 3 | 2 | Fully | Yes | | RRT_RTR_TRR | 2 | 3 | 3 | Partially | Yes | | RTRT_TRTR | 2 | 4 | 2 | Fully | Yes | | RRTT_TTRR | 2 | 4 | 2 | Fully | Yes | | RTTR_TRRT | 2 | 4 | 2 | Fully | Yes | | RRTT_RTTR_TRRT_TTRR | 2 | 4 | 4 | Fully | Yes | | RTRT_RTTR_TRRT_TRTR | 2 | 4 | 4 | Fully | Yes | | RR_TT | 2 | >1 | 2 | Fully | No | | RST_RTS_SRT_STR_TRS_TSR | 3 | 3 | 6 | No | Yes | | ADBC_BACD_CBDA_DCAB | 4 | 4 | 4 | No | Yes |

Examples

julia> data = dataset(joinpath("bioequivalence", "RT_TR", "SLF2014_1"))
36×4 DataFrame
 Row │ id     sequence  period  AUC
     │ Int64  String3   Int64   Float64
─────┼──────────────────────────────────
   1 │     1  RT             1   181.09
   2 │     1  RT             2   210.14
   3 │     2  RT             1   114.48
   4 │     2  RT             2    98.72
   5 │     3  TR             1   225.95
   6 │     3  TR             2   241.09
   7 │     4  RT             1   176.91
   8 │     4  RT             2   186.65
   9 │     5  TR             1   147.01
  10 │     5  TR             2   139.56
  11 │     6  TR             1    97.53
  ⋮  │   ⋮       ⋮        ⋮        ⋮
  27 │    14  TR             1   179.96
  28 │    14  TR             2   181.09
  29 │    15  TR             1   173.86
  30 │    15  TR             2   206.66
  31 │    16  RT             1   144.0
  32 │    16  RT             2   143.25
  33 │    17  RT             1   185.1
  34 │    17  RT             2   192.22
  35 │    18  TR             1   117.99
  36 │    18  TR             2   125.5
                         15 rows omitted

julia> output = pumas_be(data)

sequence ╲ period │ 1  2
──────────────────┼─────
RT                │ 9  9
TR                │ 9  9

-----------------------------------------------------------------------------------------
Paradigm: Non replicated crossover design
Model: Linear model
Criteria: Standard ABE
Endpoint: AUC
Formulations: Reference(R), Test(T)
-----------------------------------------------------------------------------------------
                                             Results(AUC)     Assessment   Criteria      
-----------------------------------------------------------------------------------------
T             Geometric Mean T/R Ratio (%)   95.09                                       
              Degrees of Freedom             16                                          
              90% Confidence Interval (%)    [90.76, 99.62]   Pass         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
Variability   CV (%) | σ̂                     8.01 | 0.08                                 
-----------------------------------------------------------------------------------------
ANOVA         Treatment (p-value)            0.077                                       
              Sequence (p-value)             2.0e-5                                      
              Period (p-value)               0.01702                                     
-----------------------------------------------------------------------------------------

julia> output = pumas_be(data, nonparametric = true)

sequence ╲ period │ 1  2
──────────────────┼─────
RT                │ 9  9
TR                │ 9  9

-----------------------------------------------------------------------------
Paradigm: Nonparametric analysis
Model: Signed rank test
Criteria: Standard ABE
Endpoint: AUC
Formulations: Reference(R), Test(T)
-----------------------------------------------------------------------------
                                  Results(AUC)    Assessment   Criteria      
-----------------------------------------------------------------------------
T   90% Confidence Interval (%)   [89.9, 99.88]   Pass         CI ⊆ [80, 125]
-----------------------------------------------------------------------------

julia> data = dataset(joinpath("bioequivalence", "RTT_TRR", "PJ2017_4_1"))
285×5 DataFrame
 Row │ id     sequence  period  AUC       Cmax
     │ Int64  String3   Int64   Float64?  Float64?
─────┼─────────────────────────────────────────────
   1 │   101  TRR            1     12.26     0.511
   2 │   101  TRR            2     16.19     0.688
   3 │   101  TRR            3     11.34     0.533
   4 │   102  TRR            1    397.98    13.27
   5 │   102  TRR            2    267.63     7.933
   6 │   102  TRR            3    487.55    12.952
   7 │   103  TRR            1    243.81    16.771
   8 │   103  TRR            2    141.7      6.926
   9 │   103  TRR            3    198.44     9.257
  10 │   109  TRR            1    182.52     8.816
  11 │   109  TRR            2    112.34     4.921
  ⋮  │   ⋮       ⋮        ⋮        ⋮         ⋮
 276 │   186  RTT            3     87.63     4.87
 277 │   190  RTT            1     82.78     3.88
 278 │   190  RTT            2    164.56     7.37
 279 │   190  RTT            3    213.98     7.01
 280 │   191  RTT            1     98.86     4.59
 281 │   191  RTT            2     99.02     2.96
 282 │   191  RTT            3     75.48     2.38
 283 │   194  RTT            1     21.29     1.51
 284 │   194  RTT            2     46.3      2.74
 285 │   194  RTT            3     15.41     1.41
                                   264 rows omitted

julia> output = pumas_be(data)

sequence ╲ period │  1   2   3
──────────────────┼───────────
RTT               │ 46  45  43
TRR               │ 47  47  47

-----------------------------------------------------------------------------------------
Paradigm: Replicated crossover that does not support reference scaling
Model: Mixed model (unequal variance)
Criteria: Standard ABE
Endpoint: AUC
Formulations: Reference(R), Test(T)
-----------------------------------------------------------------------------------------
                                             Results(AUC)     Assessment   Criteria      
-----------------------------------------------------------------------------------------
T             Geometric Mean T/R Ratio (%)   97.38                                       
              Degrees of Freedom             148.7                                       
              90% Confidence Interval (%)    [86.86, 109.2]   Pass         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
Variability   CVᵣ (%) | σ̂ᵣ                   42.75 | 0.4097                              
              CVₜ (%) | σ̂ₜ                   69.65 | 0.6289                              
-----------------------------------------------------------------------------------------
ANOVA         Treatment (p-value)            0.7013                                      
              Sequence (p-value)             0.2506                                      
              Period (p-value)               0.01209                                     
-----------------------------------------------------------------------------------------
Bioequivalence.reference_scaled_acceptance_boundsFunction
reference_scaled_acceptance_bounds(σwr::Real, θ::Real)
reference_scaled_acceptance_bounds(obj::BioequivalenceEndpointOutput)

Return the lower and upper bounds based on the reference within subject variability and regulatory parameter.

Reference: European Medicines Agency (2010). "GUIDELINE ON THE INVESTIGATION OF BIOEQUIVALENCE": 4.1.10 Highly variable drugs or drug products. Doc. Ref.: CPMP/EWP/QWP/1401/98 Rev. 1/ Corr **

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "PJ2017_4_3"));

julia> output = pumas_be(data)

sequence ╲ period │ 1  2  3  4
──────────────────┼───────────
RTTR              │ 8  8  8  8
TRRT              │ 9  9  9  8

-----------------------------------------------------------------------------------------
Paradigm: Replicated crossover that supports reference scaling
Model: Mixed model (unequal variance)
Criteria: Standard ABE
Endpoint: AUC
Formulations: Reference(R), Test(T)
-----------------------------------------------------------------------------------------
                                             Results(AUC)     Assessment   Criteria
-----------------------------------------------------------------------------------------
T             Geometric Mean T/R Ratio (%)   103.6
              Degrees of Freedom             15.25
              90% Confidence Interval (%)    [99.31, 108.2]   Pass         CI ⊆ [80, 125]
-----------------------------------------------------------------------------------------
Variability   CVᵣ (%) | σ̂ᵣ                   8.02 | 0.0801
              CVₜ (%) | σ̂ₜ                   10.84 | 0.1081
              Variability Ratio (%)          135
-----------------------------------------------------------------------------------------
ANOVA         Treatment (p-value)            0.1624
              Sequence (p-value)             0.3184
              Period (p-value)               0.6651
-----------------------------------------------------------------------------------------

julia> reference_scaled_acceptance_bounds(output)
(0.9381852023891446, 1.0658876280007832)

julia> reference_scaled_acceptance_bounds(geocv2sigma(30), 0.76)
(0.13774539477808087, 7.259770837428591)

julia> reference_scaled_acceptance_bounds(geocv2sigma(21.42), (log(1 / 0.9) / 0.1)^2)
(0.06401589407631314, 15.62112057371101)
Bioequivalence.result_summary_tableMethod
result_summary_table(endpoint_output::BioequivalenceEndpointOutput)

Creates a SummaryTables.Table representing the endpoint output.

Bioequivalence.run_beMethod
run_be(
    data::AbstractDataFrame;
    reference_scale::Real = (log(1.25) / 0.25)^2,
    cv_max::Real = Inf,
    nonparametric::Bool = false,
    homogeneity::Union{Bool, Nothing} = nothing,
    userepeatedobsonly::Bool = true,
    level::Real = 0.9,
    alpha::Real = 0.1,
    level_y::Real = 0.95,
    reml::Bool = true,
    sigdigits::Integer = 4,
    ) -> BioequivalenceEndpointOutput

BioequivalenceEndpointOutput constructor.

See also: BioequivalenceEndpointOutput.

Arguments

  • data: must have id, sequence, period, and an endpoint.
  • nonparametric: whether to use a nonparametric analysis (uncommon and usually reserved for Tmax)
  • homogeneity: whether formulation groups should be modeled with equal variance
  • userepeatedobsonly: whether estimating the within subject variability should only use repeated observations
  • reference_scale: 𝜃 for reference scale (FDA ≈ 0.797, FDA/NTI ≈ 1.11, EMA = 0.76)
  • cv_max: maximum within subject variability for reference scaling (FDA = Inf, FDA/NTI = 0.2142, EMA = 0.5)
  • reml: whether the linear mixed model should use restricted maximum likelihood or maximum likelihood.
  • level: applies to the confidence intervals for the GMR.
  • alpha: applies to the upper bound of the within subject variability ratio
  • level_y: applies to the critical boundary for reference-scaled average bioequivalence
  • sigdigits: results given with how many significant digits.
  • endpoint_name the name of the endpoint

Current designs include: nonparametric, parallel, and various crossover designs

DescriptionTreatmentsPeriodsSequencesReplicatedCrossover
R_T212NoNo
RT_TR222NoYes
RR_RT_TR_TT224NoYes
RTR_TRT232FullyYes
RTR_TRR232PartiallyYes
RTT_TRR232FullyYes
RRT_RTR_TRR233PartiallyYes
RTRT_TRTR242FullyYes
RRTT_TTRR242FullyYes
RTTR_TRRT242FullyYes
RRTT_RTTR_TRRT_TTRR244FullyYes
RTRT_RTTR_TRRT_TRTR244FullyYes
RR_TT2>12FullyNo
RST_RTS_SRT_STR_TRS_TSR336NoYes
ADBC_BACD_CBDA_DCAB444NoYes

Examples

julia> data = dataset(joinpath("bioequivalence", "RT_TR", "SLF2014_1"))
36×4 DataFrame
 Row │ id     sequence  period  AUC
     │ Int64  String3   Int64   Float64
─────┼──────────────────────────────────
   1 │     1  RT             1   181.09
   2 │     1  RT             2   210.14
   3 │     2  RT             1   114.48
   4 │     2  RT             2    98.72
   5 │     3  TR             1   225.95
   6 │     3  TR             2   241.09
   7 │     4  RT             1   176.91
   8 │     4  RT             2   186.65
   9 │     5  TR             1   147.01
  10 │     5  TR             2   139.56
  11 │     6  TR             1    97.53
  ⋮  │   ⋮       ⋮        ⋮        ⋮
  27 │    14  TR             1   179.96
  28 │    14  TR             2   181.09
  29 │    15  TR             1   173.86
  30 │    15  TR             2   206.66
  31 │    16  RT             1   144.0
  32 │    16  RT             2   143.25
  33 │    17  RT             1   185.1
  34 │    17  RT             2   192.22
  35 │    18  TR             1   117.99
  36 │    18  TR             2   125.5
                         15 rows omitted

julia> pkdata = preprocess_be(data)
36×6 DataFrame
 Row │ id    id_within_sequence  sequence  period  formulation  endpoint
     │ Cat…  Cat…                Cat…      Cat…    Cat…         Float64
─────┼───────────────────────────────────────────────────────────────────
   1 │ 1     1                   RT        1       R             5.19899
   2 │ 1     1                   RT        2       T             5.34777
   3 │ 2     2                   RT        1       R             4.7404
   4 │ 2     2                   RT        2       T             4.59229
   5 │ 3     1                   TR        1       T             5.42031
   6 │ 3     1                   TR        2       R             5.48517
   7 │ 4     3                   RT        1       R             5.17564
   8 │ 4     3                   RT        2       T             5.22924
   9 │ 5     2                   TR        1       T             4.9905
  10 │ 5     2                   TR        2       R             4.93849
  11 │ 6     3                   TR        1       T             4.58016
  ⋮  │  ⋮            ⋮              ⋮        ⋮          ⋮          ⋮
  27 │ 14    7                   TR        1       T             5.19273
  28 │ 14    7                   TR        2       R             5.19899
  29 │ 15    8                   TR        1       T             5.15825
  30 │ 15    8                   TR        2       R             5.33107
  31 │ 16    8                   RT        1       R             4.96981
  32 │ 16    8                   RT        2       T             4.96459
  33 │ 17    9                   RT        1       R             5.2209
  34 │ 17    9                   RT        2       T             5.25864
  35 │ 18    9                   TR        1       T             4.7706
  36 │ 18    9                   TR        2       R             4.83231
                                                          15 rows omitted

julia> output = run_be(pkdata)

sequence ╲ period │ 1  2
──────────────────┼─────
RT                │ 9  9
TR                │ 9  9

─────────────────────────────────────────────────────────────────────────────────────────────
                δ        SE        lnLB         lnUB       GMR        LB        UB         CV
─────────────────────────────────────────────────────────────────────────────────────────────
T - R  -0.0503868  0.026658  -0.0969286  -0.00384499  0.950862  0.907621  0.996162  0.0801021
─────────────────────────────────────────────────────────────────────────────────────────────
Bioequivalence.sigma2geocvMethod
sigma2geocv(σw::Union{Real,Missing}) = √(exp(σw^2) - 1)

Transform the σ parameter of a log-normal distribution to the coefficient of variation (CV).

Examples

julia> sigma2geocv(0.294)
0.3004689459216001
Bioequivalence.stat_tests_pvaluesMethod
stat_tests_pvalues(data::AbstractDataFrame)

Returns a named tuple of p values with p_formulation, p_period, p_subject_in_group.

Bioequivalence.study_paradigmMethod
study_paradigm(data::AbstractDataFrame, nonparametric::Bool)::EndpointStudyParadigm

Determines the study paradigm of a dataset.

Bioequivalence.study_paradigmMethod
study_paradigm(be_output::BioequivalenceEndpointOutput)::EndpointStudyParadigm

Determines the study paradigm used in a bioequivalence study for an endpoint.

Bioequivalence.update_rsabe_theta!Method
update_rsabe_theta!(obj::ReferenceScaledAverageBioequivalance, 𝜃::Real) -> ReferenceScaledAverageBioequivalance

Modifies in-place the 𝜃 of the ReferenceScaledAverageBioequivalance and updates the associated critical boundary.

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "SLTGSF2020_DS16"));

julia> pkdata = preprocess_be(data, endpoint = :PK);

julia> rsabe = ReferenceScaledAverageBioequivalance(pkdata, 0.76)
Critical boundary: -0.0416
Regulatory parameter: 0.76
95.0% upper confidence bound with 36.0 degrees of freedom

julia> update_rsabe_theta!(rsabe, 1.11)
Critical boundary: -0.1019
Regulatory parameter: 1.11
95.0% upper confidence bound with 36.0 degrees of freedom
Bioequivalence.within_subject_variabilityMethod
within_subject_variability(
    data::AbstractDataFrame;
    userepeatedobsonly::Bool = true
    allownonreplicated::Bool = false,
    homogeneity::Union{Bool,Nothing} = nothing,
)

Return the within-subject variability estimate and degrees of freedom. It uses a linear model of the log-transformed PK response with fixed effects for subject ID and period. If userepeatedobsonly, data used is a sample with only observations from repeated subject/treatment. If allownonreplicated, the function returns a NamedTuple of missings instead of throwing an error when the passed formulation is not replicated in any sequences. This option is only relevant for partially replicated designs.

The homogeneity argument specifies if equal variances are assumed between formulations. When set to true, multiple formulations are expected in data. When set to false, only a single formulation should be available in data. In this case, design must be replicated. The default value of homogeneity is false for replicated designs and true otherwise.

References:

Schütz H, Tomashevskiy M, Labes D, Shitova A, González-de la Parra M, Fuglsang A. 2020. Reference Datasets for Studies in a Replicate Design Intended for Average Bioequivalence with Expanding Limits. AAPS J. 22(2): Article 44. DOI: 10.1208/s12248-020-0427-6.

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "PJ2017_4_3"));

julia> pkdata = preprocess_be(data);

julia> combine(groupby(pkdata, :formulation), within_subject_variability)
2×3 DataFrame
 Row │ formulation  σw         k
     │ Cat…         Float64    Float64
─────┼─────────────────────────────────
   1 │ R            0.0800952     15.0
   2 │ T            0.108075      14.0

julia> data = dataset(joinpath("bioequivalence", "RRT_RTR_TRR", "SLTGSF2020_DS02"));

julia> pkdata = preprocess_be(data, endpoint = :PK);

julia> combine(groupby(pkdata, :formulation), t -> within_subject_variability(t; allownonreplicated=true))
2×3 DataFrame
 Row │ formulation  σw              k
     │ Cat…         Float64?        Float64?
─────┼────────────────────────────────────────
   1 │ R                  0.113973       21.0
   2 │ T            missing         missing
Bioequivalence.within_subject_variability_ratioFunction
within_subject_variability_ratio(
    σ::AbstractVector{<:Union{Real, Missing}},
    k::AbstractVector{<:Union{Real, Missing}},
    level::Real = 0.95
    ) -> Vector{NamedTuple{(:σ_ratio, :σ⁺), ...}}

within_subject_variability_ratio(
    data::AbstractDataFrame,
    level::Real = 0.95
    ) -> DataFrame

Return the within-subject variability ratio and upper bounds. σ contains the estimated within subject variability. k contains the associated degrees of freedom. level determines the confidence level for the upper bound.

Examples

julia> data = dataset(joinpath("bioequivalence", "RTTR_TRRT", "PJ2017_4_3"));

julia> pkdata = preprocess_be(data);

julia> wsv_estimates = combine(groupby(pkdata, :formulation), within_subject_variability)
2×3 DataFrame
 Row │ formulation  σw         k
     │ Cat…         Float64    Float64
─────┼─────────────────────────────────
   1 │ R            0.0800952     15.0
   2 │ T            0.108075      14.0

julia> within_subject_variability_ratio(wsv_estimates[!, :σw], wsv_estimates[!, :k])
1-element Vector{@NamedTuple{σ_ratio::Float64, σ⁺::Float64}}:
 (σ_ratio = 1.349328424089969, σ⁺ = 2.1176303305572595)

julia> within_subject_variability_ratio(wsv_estimates)
2×5 DataFrame
 Row │ formulation  σw         k        σ_ratio        σ⁺
     │ Cat…         Float64    Float64  Float64?       Float64?
─────┼───────────────────────────────────────────────────────────────
   1 │ R            0.0800952     15.0  missing        missing
   2 │ T            0.108075      14.0        1.34933        2.11763