Git Product home page Git Product logo

mediana's Introduction

Mediana

CRAN_Status_Badge CRAN_Logs_Badge CRAN_Logs_Badge_Total

Mediana is an R package which provides a general framework for clinical trial simulations based on the Clinical Scenario Evaluation approach. The package supports a broad class of data models (including clinical trials with continuous, binary, survival-type and count-type endpoints as well as multivariate outcomes that are based on combinations of different endpoints), analysis strategies and commonly used evaluation criteria.

Find out more at http://gpaux.github.io/Mediana/ and check out the case studies.

Installation

Get the released version from CRAN:

install.packages("Mediana")

Or the development version from github:

# install.packages("devtools")
devtools::install_github("gpaux/Mediana", build_opts = NULL)

Vignettes

Mediana includes 3 vignettes. In particular, an introduction of the package and several case studies:

vignette(topic = "mediana", package = "Mediana")
vignette(topic = "case-studies", package = "Mediana")

Online Manual

A detailed online manual is accessible at http://gpaux.github.io/Mediana/

References

Clinical trial optimization using R book

Clinical Trial Optimization Using R explores a unified and broadly applicable framework for optimizing decision making and strategy selection in clinical development, through a series of examples and case studies.It provides the clinical researcher with a powerful evaluation paradigm, as well as supportive R tools, to evaluate and select among simultaneous competing designs or analysis options. It is applicable broadly to statisticians and other quantitative clinical trialists, who have an interest in optimizing clinical trials, clinical trial programs, or associated analytics and decision making.

This book presents in depth the Clinical Scenario Evaluation (CSE) framework, and discusses optimization strategies, including the quantitative assessment of tradeoffs. A variety of common development challenges are evaluated as case studies, and used to show how this framework both simplifies and optimizes strategy selection. Specific settings include optimizing adaptive designs, multiplicity and subgroup analysis strategies, and overall development decision-making criteria around Go/No-Go. After this book, the reader will be equipped to extend the CSE framework to their particular development challenges as well.

Mediana R package has been widely used to implement the case studies presented in this book. The detailed description and R code of these case studies are available on this website.

Publications

The Mediana package has been successfully used in multiple clinical trials to perform power calculations as well as optimally select trial designs and analysis strategies (clinical trial optimization). For more information on applications of the Mediana package, download the following papers:

Citation

If you find Mediana useful, please cite it in your publications:

citation("Mediana")
#> 
#> To cite package 'Mediana' in publications use:
#> 
#>   Gautier Paux and Alex Dmitrienko. (2019). Mediana: Clinical Trial Simulations. R
#>   package version 1.0.8. http://gpaux.github.io/Mediana/
#> 
#> A BibTeX entry for LaTeX users is
#> 
#>   @Manual{,
#>     title = {Mediana: Clinical Trial Simulations},
#>     author = {Gautier Paux and Alex Dmitrienko.},
#>     year = {2019},
#>     note = {R package version 1.0.8},
#>     url = {http://gpaux.github.io/Mediana/},
#>   }
#> 
#> ATTENTION: This citation information has been auto-generated from the package DESCRIPTION
#> file and may need manual editing, see 'help("citation")'.

mediana's People

Contributors

gpaux avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mediana's Issues

Anova/Ancova

Hi,

I have to say that this is a very nice package for RCT simulation. I was wondering if there is an easy way to incorporate Anova/ Ancova analysis in the analysis part.

Thanks in advance for the comment

Enrollment distribution and mean events

Hi there,

Thanks for developing the package. It's very useful for clinical trial simulations!

I have one question. It's about the enrollment distribution. Can it be any prespecified vector, such as c(1, 3, 5, 10, 20, 0, 0, 0, 50, 100, 120)? (0, 0, 0) means the enrolment is on hold. If this is allowed, it will cover a lot of practical situations.

Sincerely,
Bob

Restricted mean survival time

Hi! Nice package... should be useful!
When using survival outcomes, is it possible to use restricted mean survival times at all? e.g. as statistics by group, or RMST difference.
That would be a really nice addition if it doesnt exist to date...

Marginal power calculation with sample size higher than 1000 in survival

Congratulations for your nice package

I am trying to estimate marginal power in a clinical scenario with different sample sizes. The problem is when I reach large sample size (> 1000), the result gets NaN.
I have no idea why it is happening but seems rare...
I attach the example.
I would really appreciate if you can help me with this. Probably, I am not considering some factor.

Thanks in advance, Irene

Requirements

require(Mediana)

Adjusting rate to experimental data

analysis.model = AnalysisModel() +
Test(id = "Placebo vs treatment",
samples = samples("Placebo", "Treatment"),
method = "LogrankTest") +
Statistic(id = "Events Placebo",
samples = samples("Placebo"),
method = "EventCountStat") +
Statistic(id = "Events Treatment",
samples = samples("Treatment"),
method = "EventCountStat") +
Statistic(id = "Patients Placebo",
samples = samples("Placebo"),
method = "PatientCountStat") +
Statistic(id = "Patients Treatment",
samples = samples("Treatment"),
method = "PatientCountStat")

evaluation.model = EvaluationModel() +
Criterion(id = "Marginal power",
method = "MarginalPower",
tests = tests("Placebo vs treatment"),
labels = c("Placebo vs treatment"),
par = parameters(alpha = 0.025)) +
Criterion(id = "Mean Events",
method = "MeanSumm",
statistics = statistics("Events Placebo", "Events Treatment"),
labels = c("Mean Events Placebo", "Mean Events Treatment")) +
Criterion(id = "Mean Patients",
method = "MeanSumm",
statistics = statistics("Patients Placebo", "Patients Treatment"),
labels = c("Mean Patients Placebo", "Mean Patients Treatment"))

sim.parameters = SimParameters(n.sims = 1000, proc.load = "full", seed = 42938001)

data.model = DataModel() +
OutcomeDist(outcome.dist = "ExpoDist", outcome.type = "event") +
Sample(id = "Placebo",
outcome.par = parameters(parameters(rate =0.05))) +
Sample(id = "Treatment",
outcome.par = parameters(parameters(rate =0.05*0.6))) +
SampleSize(1500) +
Design(enroll.period = 1,
study.duration = 5,
enroll.dist = "UniformDist",
dropout.dist = "ExpoDist",
dropout.dist.par = parameters(rate = 0.0115))

results = CSE(data.model, analysis.model, evaluation.model, sim.parameters)

Integer overflow

Thanks for this interesting package. I've been exploring some survival models and I've noticed that there is an integer overflow error when samples sizes are slightly larger than 2000 cases, so no calculations of Marginal Power, Hazard ratio or p-values are given, showing a NA/NaN instead.
Reviewing the code, the problem is in "LogrankTest.R", line 40. Multiplication of large numbers in that line causes the error, as the result is higher than the maximum allowed value in R.
It can be solved by adding an "as.numeric" before the first term of the multiplication, so the result is converted to numeric:
data$v1 = ifelse(data$n.risk.prior > 1, (as.numeric(data$n.risk1.prior) * data$n.risk2.prior * data$eventtot * (data$n.risk.prior - data$eventtot))/(data$n.risk.prior^2 * (data$n.risk.prior - 1)), 0)
Could this be corrected in the main branch? Thank you very much for your contribution.

[Question] Could you, please, cross-validate the calculation gMCP vs. Mediana in this scenario?

For this 2-family parallel gatekeeper with Hochberg truncated at: 0.5 in the 1st family and 1 (classic) in the 2nd family:

obraz

I get a discrepancy between gMCP and Mediana.

Mediana:

rawp   <- c(0.01, 0.013, 0.01, 0.01)
family <- families(family1 = c(1, 2), family2 = c(3, 4))
gamma  <- families(family1 = 0.5, family2 = 1)

AdjustPvalues(rawp,
              proc = "ParallelGatekeepingAdj",
              par = parameters(family = family,
                               proc = families(family1 ="HochbergAdj", family2 = "HochbergAdj"),
                               gamma = gamma))

[1] 0.01733333 0.01733333 0.01733333 0.01733333

gMCP with Simes test:

m <- rbind(H1=c(0, 0.5, 0.25, 0.25),
           H2=c(0.5, 0, 0.25, 0.25),
           H3=c(0, 0, 0, 1),
           H4=c(0, 0, 1, 0))
weights <- c(0.5, 0.5, 0, 0)
graph <- new("graphMCP", m=m, weights=weights)
pvalues <- c(0.01, 0.013, 0.01, 0.01)
gMCP(graph, pvalues, test="Simes", alpha=0.05)

obraz

I get from the CTP:

Remaining hypotheses (new numbering):
1: H1
2: H2
3: H3
4: H4
Subset {4} (padj: 0.01): p_4=0.01<=a*(w_4)     =0.05*(1)=0.05
Subset {3} (padj: 0.01): p_3=0.01<=a*(w_3)     =0.05*(1)=0.05

Subset {3,4} (padj: 0.01): p_4=0.01<=a*(w_3+w_4)     =0.05*(0.5+0.5)=0.05

Subset {2} (padj: 0.0173333333333333): p_2=0.013<=a*(w_2)     =0.05*(0.75)=0.0375

Subset {2,4} (padj: 0.013): p_4=0.01<=a*(w_4)     =0.05*(0.25)=0.0125
Subset {2,3} (padj: 0.013): p_3=0.01<=a*(w_3)     =0.05*(0.25)=0.0125
Subset {2,3,4} (padj: 0.013): p_4=0.01<=a*(w_3+w_4)     =0.05*(0.125+0.125)=0.0125

Subset {1} (padj: 0.0133333333333333): p_1=0.01<=a*(w_1)     =0.05*(0.75)=0.0375

Subset {1,4} (padj: 0.01): p_4=0.01<=a*(w_1+w_4)     =0.05*(0.75+0.25)=0.05
Subset {1,3} (padj: 0.01): p_3=0.01<=a*(w_1+w_3)     =0.05*(0.75+0.25)=0.05
Subset {1,3,4} (padj: 0.01): p_4=0.01<=a*(w_1+w_3+w_4)     =0.05*(0.75+0.125+0.125)=0.05
Subset {1,2} (padj: 0.013): p_2=0.013<=a*(w_1+w_2)     =0.05*(0.5+0.5)=0.05
Subset {1,2,4} (padj: 0.013): p_4=0.01<=a*(w_1+w_4)     =0.05*(0.5+0)=0.025
Subset {1,2,3} (padj: 0.013): p_3=0.01<=a*(w_1+w_3)     =0.05*(0.5+0)=0.025
Subset {1,2,3,4} (padj: 0.013): p_4=0.01<=a*(w_1+w_3+w_4)     =0.05*(0.5+0+0)=0.025

Let's filter it:
obraz

For the same parameters and Holm (Bonferroni's approach) it agrees.


EDIT: Checked also with multxpert:

F1 <- list(label = "F1", rawp=c(0.01, 0.013), proc = "Hochberg", procpar = 0.5)
F2 <- list(label = "F2", rawp=c(0.01, 0.01),  proc = "Hochberg", procpar = 1)

multxpert::pargateadjp(gateproc = list(F1, F2), independence = TRUE, printDecisionRules=TRUE)

Hypothesis testing problem

Global familywise error rate=0.05
Independence condition is imposed (the families are tested from first to last) 

Family 1 (F1) is tested using Hochberg procedure (truncation parameter=0.5) at alpha1=0.05.

Null hypothesis 1 (raw p-value=0.01) is rejected.
Null hypothesis 2 (raw p-value=0.013) is rejected.

Details on the decision rule for this family can be obtained by running the PValAdjP function for Hochberg procedure with gamma=0.5 and alpha=0.05.

One or more null hypotheses are rejected in Family 1 and the parallel gatekeeping procedure passes this family. Based on the error rate function of Hochberg procedure (truncation parameter=0.5), alpha2=0.05 is carried over to Family 2.

Family 2 (F2) is tested using Hochberg procedure (truncation parameter=1) at alpha2=0.05.

Null hypothesis 3 (raw p-value=0.01) is rejected.
Null hypothesis 4 (raw p-value=0.01) is rejected.

Details on the decision rule for this family can be obtained by running the PValAdjP function for Hochberg procedure with gamma=1 and alpha=0.05.

  Family Procedure Parameter Raw.pvalue Adj.pvalue
1     F1  Hochberg       0.5      0.010     0.0173
2     F1  Hochberg       0.5      0.013     0.0173
3     F2  Hochberg       1.0      0.010     0.0173
4     F2  Hochberg       1.0      0.010     0.0173

Literature:

PS: in any case, gMCP seems to use the formulas provided here:

No censoring when SampleSize is used in a time-to-event endpoint

In version 1.0.1 of the package, the only way to get censored observations is to use the Event object. In some cases, the user might want to use the SampleSize object or define sample size within each Samples object, and define a Design object to censure observations.

Example:

# Case study 1
# Clinical trial in patients with metastatic colorectal cancer with censoring

# Sample size parameters
event.count.total = c(390, 420)
randomization.ratio = c(1,2)

# Outcome parameters
median.time.placebo = 6
rate.placebo = log(2)/median.time.placebo
outcome.placebo = parameters(rate = rate.placebo)
median.time.treatment = 9
rate.treatment = log(2)/median.time.treatment
outcome.treatment = parameters(rate = rate.treatment)

# Dropout parameters
dropout.par = parameters(rate = 0.0115)

# Data model
case.study1.data.model = DataModel() +
  OutcomeDist(outcome.dist = "ExpoDist") +
  Event(n.events = event.count.total, rando.ratio = randomization.ratio) +
  Design(enroll.period = 9,
         study.duration = 21,
         enroll.dist = "UniformDist",
         dropout.dist = "ExpoDist",
         dropout.dist.par = dropout.par) +
  Sample(id = "Placebo",
         outcome.par = parameters(outcome.placebo)) +
  Sample(id = "Treatment",
         outcome.par = parameters(outcome.treatment))

In this case, no problem as Event has been used. If Sample size is used such as in the following example, no censoring is made even if Design has been used, and all patients will get the event.

# Case study 1
# Clinical trial in patients with metastatic colorectal cancer with censoring

# Outcome parameters
median.time.placebo = 6
rate.placebo = log(2)/median.time.placebo
outcome.placebo = parameters(rate = rate.placebo)
median.time.treatment = 9
rate.treatment = log(2)/median.time.treatment
outcome.treatment = parameters(rate = rate.treatment)

# Dropout parameters
dropout.par = parameters(rate = 0.0115)

# Data model
case.study1.data.model = DataModel() +
  OutcomeDist(outcome.dist = "ExpoDist") +
  SampleSize(350) +
  Design(enroll.period = 9,
         study.duration = 21,
         enroll.dist = "UniformDist",
         dropout.dist = "ExpoDist",
         dropout.dist.par = dropout.par) +
  Sample(id = "Placebo",
         outcome.par = parameters(outcome.placebo)) +
  Sample(id = "Treatment",
         outcome.par = parameters(outcome.treatment))

Survival models result in simular number of events per arm regardless of rate

Using a slightly modified version of case study 4 (survival with censoring), setting the rate parameters for two arms at quite different values and using the standard outcome.type rather than event based, the number of events in simulated datasets is very similar. I wonder if there is a bug because i would expect a different number of events in the two arms if the rates are different... or is there some flaw in my thinking?

# Dropout parameters
dropout.par <- parameters(rate = 0.0115)

# Design parameters
design <- Design(enroll.period = 9,
                 study.duration = 21,
                 enroll.dist = "UniformDist",
                 dropout.dist = "ExpoDist",
                 dropout.dist.par = dropout.par) 

# Outcome parameters
median.time.placebo <- 3
rate.placebo <- log(2)/median.time.placebo
outcome.placebo <- parameters(rate = rate.placebo)
median.time.treatment <- 20
rate.treatment <- log(2)/median.time.treatment
outcome.treatment <- parameters(rate = rate.treatment)

# Dropout parameters
dropout.par <- parameters(rate = 0.0115)

# Data model
data.model <- DataModel() +
  OutcomeDist(outcome.dist = "ExpoDist", 
              outcome.type = "standard") +
  SampleSize(c(500,800)) + # N PER GROUP!!!
  design +
  Sample(id = "Placebo",
         outcome.par = parameters(outcome.placebo)) +
  Sample(id = "Treatment",
         outcome.par = parameters(outcome.treatment))

analysis.model <- AnalysisModel() +
  Test(id = "Placebo vs treatment",
       samples = samples("Placebo", "Treatment"),
       method = "LogrankTest") +
  Statistic(id = "Events Placebo",
            samples = samples("Placebo"),
            method = "EventCountStat") +
  Statistic(id = "Events Treatment",
            samples = samples("Treatment"),
            method = "EventCountStat")  +
  Statistic(id = "Patients Placebo",
            samples = samples("Placebo"),
            method = "PatientCountStat") +
  Statistic(id = "Patients Treatment",
            samples = samples("Treatment"),
            method = "PatientCountStat")

evaluation.model = EvaluationModel() +
  Criterion(id = "Marginal power",
            method = "MarginalPower",
            tests = tests("Placebo vs treatment"),
            labels = c("Placebo vs treatment"),
            par = parameters(alpha = 0.025))  +
  Criterion(id = "Mean Events",
            method = "MeanSumm",
            statistics = statistics("Events Placebo", "Events Treatment"),
            labels = c("Mean Events Placebo", "Mean Events Treatment")) +
  Criterion(id = "Mean Patients",
            method = "MeanSumm",
            statistics = statistics("Patients Placebo", "Patients Treatment"),
            labels = c("Mean Patients Placebo", "Mean Patients Treatment"))

# Run simulations
res <- CSE(data.model, 
           analysis.model,
           evaluation.model,
           SimParameters(n.sims = 1000, seed = 23, proc.load = "low"))

summary(res)

   sample.size outcome.parameter design.parameter multiplicity.adjustment      criterion
1            1                 1                1                       1 Marginal power
2            1                 1                1                       1    Mean Events
3            1                 1                1                       1    Mean Events
4            1                 1                1                       1  Mean Patients
5            1                 1                1                       1  Mean Patients
6            2                 1                1                       1 Marginal power
7            2                 1                1                       1    Mean Events
8            2                 1                1                       1    Mean Events
9            2                 1                1                       1  Mean Patients
10           2                 1                1                       1  Mean Patients
            test.statistic  result
1     Placebo vs treatment   1.000
2      Mean Events Placebo 405.590
3    Mean Events Treatment 405.800
4    Mean Patients Placebo 500.000
5  Mean Patients Treatment 500.000
6     Placebo vs treatment   1.000
7      Mean Events Placebo 661.814
8    Mean Events Treatment 662.282
9    Mean Patients Placebo 800.000
10 Mean Patients Treatment 800.000

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.