Regional Consistency Evaluation and Sample Size Calculation for MRCTs

Calculate conditional regional consistency probabilities and sample sizes for multi-regional clinical trials under fixed-effects and random-effects models. Supports two independent trials, regional fraction selection under symmetric designs, and doubly robust regional treatment-effect estimation. Methods include Qing et al. (2025) and Ren and Xu (2026) .


ssMRCT

R-CMD-check Testcoverage

ssMRCT calculates consistency probabilities (CP), overall sample sizes, and regional recruitment fractions for multi-regional clinical trials (MRCTs). It supports fixed-effects and random-effects designs, two independent trials, and covariate-adjusted regional treatment-effect estimation.

CP is a probability of regional consistency conditional on overall trial significance. It is different from overall power and confidence-interval coverage. For two trials, the conditioning event is that both trials are significant.

Installation

# install.packages("pak")
pak::pak("kunhaiq/ssMRCT")

Choose a function

Task Functions
Fixed-effects Method I: preserve a fraction of the overall effect conProb(), conProb2()
Find a regional fraction for a target Method I CP regFrac(), regFrac2()
Fixed-effects Method II: all regional effects are nonnegative conProbII(), conProbII2()
Random-effects sample size and Method I CP ssCPnorm(), ssCPbinary(), ssCPsurvPH(), ssCPsurvNPH()
Random-effects CP lower bound CPlbd()
Covariate-adjusted target-region ATE regATE_dr()

The suffix 2 denotes two independent trials. regFrac2() requires a symmetric trial design; it does not optimize two different regional fractions. Random-effects CP uses a shrinkage regional estimator, so it has a different interpretation from fixed-effects CP based on the raw regional effect estimate.

One trial: CP and regional fraction

Assume a one-sided significance level of 0.05, power of 0.80, treatment effect of 1, standard deviation of 4 in both arms, and equal randomization. Method I requires the regional estimate to preserve at least pi = 0.5 of the overall estimate.

library(ssMRCT)
conProb(alpha = 0.05, power = 0.8, pi = 0.5,
        rF = 0.271, d = 1, sigmaTrt = 4)
#> $CP
#> [1] 0.8000581
#>
#> $N
#> [1] 396

# Find the regional fraction needed for CP = 0.80.
design <- regFrac(alpha = 0.05, power = 0.8, pi = 0.5, CP = 0.8,
                  d = 1, sigmaTrt = 4)
design
#> $rF
#> [1] 0.2708974
#>
#> $N
#> [1] 396

N is the recommended overall sample size; rF is a continuous regional fraction. A recruitment plan must allocate whole participants to each regional arm. Multiplying N by rF alone does not establish CP for that integer allocation.

Two trials: general CP and symmetric fraction selection

The CP calculation allows different trial powers and regional fractions. Here study 2 has higher power; unspecified effect and variance parameters are inherited from study 1.

conProb2(alpha = 0.05, power1 = 0.8, power2 = 0.9,
         rF1 = 0.15, rF2 = 0.20, d1 = 1, sigmaTrt1 = 4)
#> $CP
#> [1] 0.8309535
#>
#> $N1
#> [1] 396
#>
#> $N2
#> [1] 550

For two symmetric trials, find a common fraction and verify its CP:

fraction <- regFrac2(alpha = 0.05, power = 0.8, pi = 0.5, CP = 0.8)
fraction
#> [1] 0.1530893
conProb2(alpha = 0.05, power1 = 0.8, pi = 0.5,
         rF1 = fraction, d1 = 1, sigmaTrt1 = 4)
#> $CP
#> [1] 0.8
#>
#> $N1
#> [1] 396
#>
#> $N2
#> [1] 396

Both trials must share the effect, arm-specific variances, randomization ratio, power and regional fraction for this inverse calculation. For unequal randomization ratios in conProb2() or continuous conProbII2(), specify the control means (muCtrl1, muCtrl2) because separate arm pooling can make them relevant to the pooled effect.

All-region consistency with a binary endpoint

Method II requires every regional treatment-minus-control estimate to be nonnegative. This example uses three regions, response probabilities of 0.70 and 0.55, and 2:1 treatment-to-control randomization.

set.seed(42)
binary <- conProbII(alpha = 0.025, power = 0.8, rF = c(0.2, 0.4, 0.4),
                    pTrt = 0.70, pCtrl = 0.55, randRatio = 2,
                    responseType = "binary", B = 50000)
binary[c("CP", "N", "nTrtReg", "nCtrlReg", "achievedPower", "MCSE")]
#> $CP
#> [1] 0.9151825
#>
#> $N
#> [1] 373
#>
#> $nTrtReg
#> [1] 50 99 99
#>
#> $nCtrlReg
#> [1] 25 50 50
#>
#> $achievedPower
#> [1] 0.80856
#>
#> $MCSE
#> [1] 0.001385656

The simulation uses the returned integer regional arm counts. CP is the proportion of significant trials that also meet regional consistency; zero regional effects count as consistent. achievedPower is the simulated probability of overall significance, and MCSE describes simulation uncertainty in CP. For conProbII2(), achievedPower instead refers to both trials succeeding.

Random-effects design

For a normal endpoint, supply the mean regional effect delta, between-region standard deviation tau, outcome standard deviations, and regional fractions.

ssCPnorm(alpha = 0.025, beta = 0.2, delta = 0.25, tau = 0.1,
         sigma1r = 1, sigma0r = 1, randRatio = 1,
         pi = 0.5, target = 1, f = c(0.2, 0.3, 0.5))
#> $n0
#> [1] 459
#>
#> $n1
#> [1] 459
#>
#> $n
#> [1] 918
#>
#> $CP
#> [1] 0.9934161

n0, n1 and n are overall control, treatment and total counts. CP refers to the region indexed by target. The function sizes the trial for specified overall power and then evaluates regional CP; it does not solve for a user-specified CP target. A finite sample-size solution requires tau * (qnorm(1 - alpha) + qnorm(1 - beta)) / delta < sqrt(length(f)).

ssCPbinary() uses regional response probabilities and a normal approximation. ssCPsurvPH() uses exponential survival with fixed follow-up; ssCPsurvNPH() uses RMST differences with piecewise exponential or Weibull survival and uniform censoring. These functions derive delta and tau from the unweighted mean and sample standard deviation of the supplied regional effects.

CPlbd() returns a CP lower bound and regional counts at its equality condition, not an overall allocation. Its fr argument specifies output length; it does not divide the counts by regional fractions. Counts are NA when the finite equality condition does not apply.

Calculation conventions

  • alpha is one-sided. Fixed-effects functions take power; random-effects functions take beta = 1 - power.
  • randRatio is treatment/control. sigma parameters are standard deviations, not variances. Higher effects indicate benefit; PH effects are -log(hr).
  • Method I uses pi for the fraction of the overall effect to preserve. In regATE_dr(), pi instead denotes target-region membership probability.
  • Analytical CP uses the continuous sample-size design. Returned integer counts are recommendations; CP is not recalculated after regional rounding. Binary Method II simulation uses the actual returned integer allocation.
  • Set a seed for binary simulations and continuous Method II numerical integration. The latter uses randomized multivariate normal integration.

Regional ATE estimation

regATE_dr() estimates the treatment-minus-control average treatment effect (ATE) in a target region, using participant-level covariates and information from other regions. It returns an effect estimate, an influence-function standard error and a 95% confidence interval. This is an analysis function, not a sample-size or CP calculation.

Prepare participant-level data

The input has one row per participant:

Column Meaning
y Numeric outcome
trt Treatment assignment: 1 = treatment, 0 = control
region Region label; target_region selects one of these labels
Other numeric columns Baseline covariates used in the models

Supply complete data with both treatment arms in each region. Include only intended covariates: a numeric participant ID, for example, would otherwise be treated as a covariate. The current interface uses numeric covariates; categorical covariates need suitable numeric indicator columns.

The following example extends the one in ?regATE_dr. There are three regions with 100 participants each, equal treatment allocation within each region, one baseline covariate x, and a true treatment effect of 1.

set.seed(42)
dat <- data.frame(
  region = rep(1:3, each = 100),
  trt = unlist(lapply(1:3, function(i) sample(rep(c(0, 1), each = 50)))),
  x = rnorm(300)
)
dat$y <- dat$x + dat$trt + rnorm(300)

Estimate the target-region effect

Use region 1 as the target and regions 2 and 3 as candidate sources:

fit <- regATE_dr(dat, target_region = 1, p1 = 0.5, p0 = 0.5)
data.frame(
  estimate = fit$estimate,
  SE = fit$se_eif,
  lower95 = fit$ci[1],
  upper95 = fit$ci[2]
)
#>   estimate        SE  lower95  upper95
#> 1  1.24205 0.1096899 1.027062 1.457038

p1 and p0 are both treatment-assignment probabilities: p1 applies to the target population and p0 to the source population. They are not the treatment and control response probabilities. For a trial randomized 1:1, supplying both as 0.5 uses the known assignment probabilities.

Other commonly used options are:

  • pi = NULL (default): fit a logistic model for target-region membership given covariates. Here pi is a selection probability, not the Method I effect-preservation fraction. p1 and p0 can also be estimated by setting them to NULL. Supplied probabilities can be scalars or vectors aligned with all rows of dat.
  • v1 = "const", v0 = "const" (defaults): estimate marginal target-to-source outcome variance ratios separately in the treatment and control arms. Use v1 = 1, v0 = 1 to specify equal variances, or "log_linear" to model the ratios using covariates.
  • compute_se = FALSE: return the point estimate without its standard error and confidence interval.

Screen source regions before borrowing

With region_wise = TRUE, each source is compared with the target separately in the treatment and control arms. ANCOVA compares a common covariate model with a model allowing a region difference and region-by-covariate interactions. A source is excluded if either p-value is below check_p_threshold (default 0.05), and the estimator is refitted using the retained sources.

To illustrate, give region 3 a larger treatment effect while keeping the target-region effect unchanged:

dat_heterogeneous <- dat
dat_heterogeneous$y <- dat$y + 1.5 * (dat$region == 3) * dat$trt

screened <- regATE_dr(
  dat_heterogeneous, target_region = 1,
  p1 = 0.5, p0 = 0.5, region_wise = TRUE,
  config = list(check_p_threshold = 0.05)
)
screened$check_results
#>   source_region  p_value_trt p_value_ctrl passed
#> 1             2 4.420211e-01    0.3072005   TRUE
#> 2             3 2.115335e-10    0.1645980  FALSE
screened$region_wise_remaining_regions
#> [1] 2

data.frame(
  analysis = c("All candidate sources", "After source screening"),
  estimate = c(screened$estimate, screened$region_wise_estimate),
  SE = c(screened$se_eif, screened$region_wise_se),
  lower95 = c(screened$ci[1], screened$region_wise_ci[1]),
  upper95 = c(screened$ci[2], screened$region_wise_ci[2])
)
#>                 analysis estimate        SE   lower95  upper95
#> 1  All candidate sources 1.778874 0.1268094 1.5303323 2.027416
#> 2 After source screening 1.149283 0.1381254 0.8785626 1.420004

estimate, se_eif and ci always describe the fit using all candidate sources. The corresponding region_wise_* entries describe the fit after screening. remaining_regions lists the original candidate sources; region_wise_remaining_regions lists the retained sources, excluding the target itself. If no sources remain, the refit uses target-region data only. Selection probabilities are re-estimated when sources are removed.

Interpretation

Borrowing assumes conditional outcome-mean exchangeability across retained regions: after accounting for covariates, the outcome mean under each treatment is shared across those regions. Double robustness concerns correct specification of either the outcome models or both the selection and treatment-assignment models, under this assumption. It does not guarantee unbiased borrowing from incompatible sources, and a nonsignificant screening test does not establish exchangeability.

The reported intervals use the estimated influence function. Intervals after screening do not include uncertainty from selecting the source regions. See ?regATE_dr for the estimator formula and complete argument descriptions.

Documentation and references

Use help(package = "ssMRCT") for the function index and ?conProb (or another function name) for arguments, formulas, return values and examples.

References

Qing, Kunhai, Xinru Ren, Shuping Jiang, Ping Yang, Menggang Yu, and Jin Xu. 2025. “Regional Consistency Evaluation and Sample Size Calculation under Two MRCTs.” Statistics in Medicine 44 (25–27): e70306. https://doi.org/10.1002/sim.70306.

Ren, Xinru, and Jin Xu. 2026. “Consistency Assessment and Regional Sample Size Calculation for MRCT under Random Effects Model.” Pharmaceutical Statistics 25 (3): e70090. https://doi.org/10.1002/pst.70090.

See NEWS.md for changes that affect calculations and returned values.

License

MIT license. See LICENSE.md for the full text.

Running tests

Run the grouped tests during development:

devtools::test()

The testthat suite covers regional fraction inversion, pooled-trial and regional-order invariance, random-effects sample sizes, PH event requirements, censored RMST moments, and regional ATE estimation and source screening. The existing tests/regression.R also checks published numerical benchmarks, exact binomial probabilities and independent simulations.

Run both suites, together with examples and package checks, before release:

devtools::check()

GitHub Actions runs both suites automatically through R CMD check.

Automated checks

GitHub Actions runs package checks on every push and pull request, and can also be started from the Actions tab. The matrix covers Windows and macOS with R-release, plus Linux with R-release, R-devel and the previous R release. Errors and warnings fail the check; notes remain in the logs for review. Check reports are saved as workflow artifacts, including successful runs.

The matrix checks examples, regression tests and help files using --as-cran. The Linux R-release job also compiles the PDF manual. All check logs and notes must be reviewed before a CRAN submission. The workflow does not publish the package to CRAN.

Test coverage

The test-coverage workflow measures line coverage on every push and pull request. It runs both tests/regression.R and the testthat suite, without coverage exclusions. The workflow summary shows the overall percentage and per-file coverage. Download the test-coverage artifact for the Cobertura XML report, uncovered-line CSV, and coverage RDS object. The README badge shows workflow status, not the coverage percentage.

To generate the same reports locally, run from the package root:

install.packages(c("covr", "xml2")) # Once, if not already installed
source(".github/scripts/coverage.R")

Reports are written to coverage/, which is excluded from Git and the package source archive. Coverage measures which lines were executed; the numerical assertions in the tests assess whether the results are correct.

Codecov uploads are optional. Enable kunhaiq/ssMRCT in Codecov and add its upload token as the GitHub repository Actions secret CODECOV_TOKEN. The workflow then uploads its report automatically. Without this secret, the GitHub summary and artifacts remain available, and the upload step is skipped.

Reference manual

It appears you don't have a PDF plugin for this browser. You can click here to download the reference manual.

install.packages("ssMRCT")

0.2.0 by Kunhai Qing, 14 hours ago


Browse source code at https://github.com/cran/ssMRCT


Authors: Kunhai Qing [aut, cre] , Xinru Ren [aut] , Jin Xu [aut]


Documentation:   PDF Manual  


MIT + file LICENSE license


Imports stats, mvtnorm, utils

Suggests testthat


See at CRAN