This vignette shows how one can correct for the bias in the trial’s effect estimate using the R package mecor. We make use of external validation data. Suppose an endpoint in a trial is measured with error, i.e., the substitute endpoint \(Y^*\) instead of the reference endpoint \(Y\) is observed.
First, we simulate some example data for a trial composed out of two groups. For example, a placebo group (\(X = 0\)) and an active comparator (\(X = 1\)). The number of individuals included in the trial is set to 1000, 500 individuals in each group. Suppose the substitute endpoint \(Y^*\) is observed instead of \(Y\). Further, suppose that an external validation set of sample size 500 is available in which both \(Y^*\) and \(Y\) are measured.
# simulate the trial's data
<- rep(c(0,1), 500)
X <- 2 * X + rnorm(1000, 0, 1) # estimand: 2
Y # introduce measurement error
<- 1.1 * Y + rnorm(1000, 0, 1)
Y_star <- cbind.data.frame(X = X, Y_star = Y_star)
trial # simulate an external validation data set
<- rnorm(100, 2, 1)
Y <- 1.1 * Y + rnorm(500, 0, 1)
Y_star <- cbind.data.frame(Y = Y, Y_star = Y_star) trial_ext
When the error is ignored, one would estimate the trial’s effect by regressing \(X\) on \(Y^*\).
# uncorrected estimate of the trial's effect:
<- lm(Y_star ~ X, data = trial)
uncor_fit $coefficients
uncor_fit#> (Intercept) X
#> -0.101728 2.307088
As you might expect, the trial’s effect estimate does not equal 2, to which value the estimand was set when generating the data. To obtain an unbiased trial effect, measurement error correction is needed. First, we estimate the parameters of the measurement error model using our external validation data:
<- lm(Y_star ~ Y, data = trial_ext)
memod_fit $coefficients
memod_fit#> (Intercept) Y
#> -0.05710055 1.12903992
Then, mecor can be used to correct for the measurement error in the trial’s effect estimate as follows:
<- mecor(MeasErrorExt(substitute = Y_star, model = memod_fit) ~ X,
cor_fit data = trial,
method = "standard",
B = 0 # for bootstrap intervals, set to e.g. 999
)
Confidence intervals for the corrected estimate can be obtained by using the summary object:
summary(cor_fit, fieller = TRUE, zerovar = TRUE)
#>
#> Call:
#> mecor(formula = MeasErrorExt(substitute = Y_star, model = memod_fit) ~
#> X, data = trial, method = "standard", B = 0)
#>
#> Coefficients Corrected Model:
#> Estimate SE SE (zerovar)
#> (Intercept) -0.039527 0.106485 0.059365
#> X 2.043407 0.115500 0.083954
#>
#> 95% Confidence Intervals:
#> Estimate LCI UCI LCI (zerovar) UCI (zerovar)
#> (Intercept) -0.039527 -0.248234 0.169181 -0.155879 0.076826
#> X 2.043407 1.817031 2.269783 1.878860 2.207954
#> LCI (fieller) UCI (fieller)
#> (Intercept) NA NA
#> X 1.827951 2.282661
#>
#> The measurement error is corrected for by application of method of moments
#>
#> Coefficients Uncorrected Model:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) -0.101728 0.067025 -1.5178 0.1294
#> X 2.307088 0.094788 24.3395 <2e-16
#>
#> 95% Confidence Intervals:
#> Estimate LCI UCI
#> (Intercept) -0.101728 -0.233254 0.029798
#> X 2.307088 2.121082 2.493094
#>
#> Residual standard error: 1.498726 on 998 degrees of freedom
When there is no external validation data available. One could conduct a sensitivity analysis by making informed guesses about the parameters values of the measurement error model. Suppose e.g. we guess the following measurement error model: \(Y^* = 1.1 Y\). The following code can be used to quantify the impact of the measurement error would be on the trial’s effect estimate:
<- mecor(MeasErrorExt(substitute = Y_star,
sens_fit model = list(coef = c(0, 1.1))) ~ X,
data = trial,
method = "standard"
)
sens_fit#>
#> Call:
#> mecor(formula = MeasErrorExt(substitute = Y_star, model = list(coef = c(0,
#> 1.1))) ~ X, data = trial, method = "standard")
#>
#> Coefficients Corrected Model:
#> (Intercept) X
#> -0.09247997 2.09735276
#>
#> Coefficients Uncorrected Model:
#> (Intercept) X
#> -0.101728 2.307088