True and false interindividual differences in the physiological response to an intervention

https://physoc.onlinelibrary.wiley.com/doi/full/10.1113/EP085070

https://github.com/eamonn2014/True-and-false-interindividual-differences-in-the-physiological-response-to-an-intervention

# Simulate a RCT

 library(nlme)

      n <- 5000

      noise <- 100           # add noise (within person var & meas. error) to the baseline & foll. up

      beta.treatment <- -250 # all trt'd subjects exp same trt effect, so no resp - non responders!!

      # beta.treatment <- runif(n,-20,-5)  # subjects vary in response to treatment

      clin.rel.diff <- 200

      

      pop_mu <- 0            # population mean 

      pop_sd <- 200          # between person SD

      ur.eligible <- -1000   # eligibility criteria for trial

     

      y.0true <- rnorm(n, pop_mu, pop_sd)                  # true baseline

      y.0observed <- y.0true + rnorm(n, 0, 1*noise)        # observed baseline 

      eligible <- ifelse(y.0observed > ur.eligible, 1, 0)  # Recruit all n as ur.eligible tiny

      treat <- 1*(runif(n)<.5)                             # random treatment allocation

      y.1true <- y.0true + (treat*beta.treatment)          # true follow up, treated only respond

      y.1observed <- y.1true + rnorm(n, 0, 1*noise)        # observed follow up, noise added 

      delta.observed <- y.1observed - y.0observed

     

      d <- data.frame(y.0true, y.0observed, eligible, treat , beta.treatment,

                      y.1true, y.1observed, delta.observed)

     

      # prob that a member of pop observed baseline is eligible

      # pnorm(ur.eligible, mean= pop_mu, sd=sqrt(pop_sd^2 + noise^2))

      # 1- pnorm( (pop_mu - ur.eligible) / sqrt(pop_sd^2+noise^2) )  # z score calc.

      

      trial <- d[d$eligible==1,]    # select the trial subjects


# First rows of trial data

 

# Focus on the intervention arm only - not recommended!


      trt <- trial[trial$treat==1,]

      trt$diff <- trt$y.1observed - trt$y.0observed

      foo <- sort(trt[,"diff"])

      plot(foo, main="Individual changes in response in treated arm

           Suggested individual differences due entirely to regression to the mean

           and random error (within subject and measurement error)",

      ylab= "Change in response", xlab="Individual subjects",

      col=ifelse(foo > -clin.rel.diff, 'red', 'blue'))

      abline(h=0, lty=3)

      abline(h=beta.treatment)

      abline(h=-clin.rel.diff, lty=2)

      # this many were not observed to have reduced response by more than 5

      # wrongly labelled as 'non responders'

         # red, no that fail to show clin relevant difference

     # mean(foo > -clin.rel.diff)     #proportion that fail to show clinically relevant difference

      

      

      ctrl <- trial[trial$treat==0,]

      ctrl$diff <- ctrl$y.1observed - ctrl$y.0observed

      foox <- sort(ctrl[,"diff"])

      #mean(foo < -clin.rel.diff)*length(foo)   # No that show clin relevant difference

      #mean(foo < -clin.rel.diff)     #proportion 


#  Treatment arm only

 

# remember they all responded to the drug !

# so why are we chasing the blue dots!!!

 

      with(trt, plot(diff ~  y.0observed, col=ifelse(diff < -clin.rel.diff, 'blue', 'black')

                     , xlab="observed baseline",  ylab="follow up - baseline"  ,

      main="Treatment arm: Individual changes against baseline, observed responders in blue", cex.main =1))

      with(trt, abline(lm(diff ~  y.0observed)))

      with(trt, abline(h=mean(beta.treatment), lty=2))

      with(trt, abline(h=-clin.rel.diff, lty=2))

     ctr <- trial[trial$treat==0,]

     ctr$diff <- ctr$y.1observed - ctr$y.0observed

 

     with(trt, cor.test( diff,   y.0observed, method="pearson"))

 


# Control arm only

 


 

       with(ctr, plot(diff ~  y.0observed, col=ifelse(diff < -clin.rel.diff, 'blue', 'black')

                      , xlab="observed baseline",  ylab="follow up - baseline"  ,

                      main="Control arm:  Individual changes against baseline, observed responders in blue", cex.main =1))

       with(ctr, abline(lm(diff ~  y.0observed)))

       with(ctr, abline(h=mean(beta.treatment), lty=2))

       with(trt, abline(h=-clin.rel.diff, lty=2))

       with(ctr, cor.test( diff,   y.0observed, method="pearson"))

     

# Analyse the trial correctly. Estimate the treatment effect adjusting for baseline

 

      f0 <- lm(y.1observed ~ y.0observed + treat, trial)

      summary(f0)

      confint(f0)

 

 

      alpha <- 0.05

 

      x <- trial[trial$treat %in% 0,"delta.observed"]

 

      lstar <- qchisq(alpha/2, df=  length(x)-1)

      rstar <- qchisq(1-alpha/2, df=  length(x)-1)

     

      up <- sqrt((length(x)-1)*var(x)/(lstar))

      lo <- sqrt((length(x)-1)*var(x)/(rstar))

      pe <- sqrt(var(x))

     

      # ctrl arm estimate with 95% CI

      print(c(pe, lo, up), digits=3)

      

      x1 <- trial[trial$treat %in% 1,"delta.observed"]

     

      lstar <- qchisq(alpha/2, df=  length(x1)-1)

      rstar <- qchisq(1-alpha/2, df=  length(x1)-1)

     

      up <- sqrt((length(x1)-1)*var(x1)/(lstar))

      lo <- sqrt((length(x1)-1)*var(x1)/(rstar))

      pe <- sqrt(var(x1))

     

      # trt arm estimate with 95% CI

      print(c(pe, lo, up), digits=3)

      

 

# Typical true interindividual variation in response. Adjust for the influence of biological variation and measurement error (removal of noise).


      # True individual response to the intervention

      sqrt(sd(x1)^2-sd(x)^2)  # can be -ve if more var in control group

      

      # LMM approach

      m1 <- lme(delta.observed~ treat + y.0observed,

          random=~1|treat , data=trial, method="REML",

          weights = varIdent(form = ~1 | treat))

     

      m0 <-lme(delta.observed~ treat + y.0observed,

          random=~1|treat , data=trial, method="REML")

      

      print(m1)

      anova(m1,m0) # are the trt ctr interindividual variation in response different?

     

      c.grp <- m1$sigma

      t.grp <- coef(m1$modelStruct$varStruct, uncons = FALSE)[[1]]*m1$sigma

     

      # true individual response to the intervention estimate

      sqrt(t.grp^2 - c.grp^2) 

      

      # truth

      sd(beta.treatment )


留言

這個網誌中的熱門文章

Bayesian reanalysis of ORBITA

Bayesian reanalysis with pymc3

Bayesian reanalysis of Apolipoprotein A1 Infusions