The post Interpretation of the AUC appeared first on Colman Statistics.

]]>HCC | Biomarker_value |
---|---|

0 | 1.063 |

1 | 1.132 |

1 | 1.122 |

1 | 1.058 |

0 | 0.988 |

0 | 1.182 |

0 | 1.037 |

0 | 1.052 |

0 | 0.925 |

1 | 1.232 |

0 | 0.911 |

0 | 0.967 |

**True Positive Rate (TPR)**or sensitivity: the proportion of actual positives that are correctly identified as such.**True Negative Rate (TNR)**or specificiy: the proportion of actual negatives that are correctly identified as such.**False Positive Rate (FPR)**or 1-specificity: the proportion of actual negatives that are wrongly identified as positives.

```
library(ROCR)
pred <- prediction(df$Biomarker_value, df$HCC )
perf <- performance(pred,"tpr","fpr")
plot(perf,col="black")
abline(a=0, b=1, col="#8AB63F")
```

The green line represents a completely uninformative test, which corresponds to an AUC of 0.5. A curve pulled close to the upper left corner indicates (an AUC close to 1 and thus) a better performing test. The ROC curve does not show the cutoff values
The ROCR package also allows to calculate the estimated AUC:
```
auc<- performance( pred, c("auc"))
unlist(slot(auc , "y.values"))
```

[1] 0.875The estimated AUC based on this ROC curve is indeed equal to 0.875, the proportion of pairs for which the value of “PeakA” is larger for HCC compared to NoHCC.

```
library(ROCR)
testy <- performance(pred,"tpr","fpr")
```

Using the - alpha.values: Cutoff
- x.values: Specificity or True Negative Rate
- y.values: Sensitivity or True Positive Rate

```
plot(testy@alpha.values[[1]], testy@x.values[[1]], type='n',
xlab='Cutoff points of the biomarker',
ylab='sensitivity or specificity')
lines(testy@alpha.values[[1]], testy@y.values[[1]],
type='s', col="#1A425C", lwd=2)
lines(testy@alpha.values[[1]], 1-testy@x.values[[1]],
type='s', col="#8AB63F", lwd=2)
legend(1.15,.85, c('sensitivity', 'specificity'),
lty=c(1,1), col=c("#1A425C", "#8AB63F"), cex=.9, bty='n')
```

The plot shows how the sensitivity increases as the specificity decreases and vice versa, in relation to the possible cutoff points of the biomarker.
```
wt <-wilcox.test(data=df, df$Biomarker_value ~ df$HCC)
1 - wt$statistic/(sum(df$HCC==1)*sum(df$HCC==0))
```

W 0.875The p-value of the Mann-Whitney U test can thus safely be used to test whether the AUC differs significantly from 0.5 (AUC of an uninformative test).

```
wt <-wilcox.test(data=df, df$Biomarker_value ~ df$HCC)
wt$p.value
```

[1] 0.04848485

```
#simulation of the data
set.seed(12345)
HCC <- rbinom (n=12, size=1, prob=0.27)
Biomarker_value <- rnorm (12,mean=1,sd=0.1) + HCC*0
# replacing the zero by a value would make the test informative
df<-data.frame (HCC, Biomarker_value)
library(knitr)
kable (head(df))
```

HCC | Biomarker_value |
---|---|

0 | 1.0630099 |

1 | 0.9723816 |

1 | 0.9715840 |

1 | 0.9080678 |

0 | 0.9883752 |

0 | 1.1817312 |

```
newdf<- expand.grid (Biomarker_value [df$HCC==0],Biomarker_value [df$HCC==1])
colnames(newdf)<- c("NoHCC", "HCC")
newdf$Pair <- seq(1,dim(newdf)[1])
```

For each pair the values of the biomarker are compared between case and control:
```
newdf$Comparison <- 1*(newdf$HCC>newdf$NoHCC)
mean(newdf$Comparison)
```

[1] 0.40625

```
newdf$Comparison<-factor(newdf$Comparison, labels=c("HCC>NoHCC","HCC<=NoHCC"))
library (knitr)
kable(head(newdf,4))
```

NoHCC | HCC | Pair | Comparison |
---|---|---|---|

1.0630099 | 0.9723816 | 1 | HCC>NoHCC |

0.9883752 | 0.9723816 | 2 | HCC>NoHCC |

1.1817312 | 0.9723816 | 3 | HCC>NoHCC |

1.0370628 | 0.9723816 | 4 | HCC>NoHCC |

```
library(data.table)
longdf = melt(newdf, id.vars = c("Pair", "Comparison"),
variable.name = "Group",
measure.vars = c("HCC", "NoHCC"))
lab<-paste("AUC = Proportion \n of green lines \nAUC=", round(table(newdf$Comparison)[2]/sum(table(newdf$Comparison)),3))
library(ggplot2)
fav.col=c("#1A425C", "#8AB63F")
ggplot(longdf, aes(x=Group, y=value))+geom_line(aes(group=Pair, col=Comparison)) +
scale_color_manual(values=fav.col)+theme_bw() +
ylab("Biomarker value") + geom_text(x=0.75,y=0.95,label=lab) +
geom_point(shape=21, size=2) +
theme(legend.title=element_blank(), legend.position="bottom")
```

```
library(ROCR)
pred <- prediction(df$Biomarker_value, df$HCC )
perf <- performance(pred,"tpr","fpr")
plot(perf,col="black")
abline(a=0, b=1, col="#8AB63F")
```

Calculating the AUC:
```
auc<- performance( pred, c("auc"))
unlist(slot(auc , "y.values"))
```

[1] 0.40625Sensitivity and specificity as a function of the cutoff points of the biomarker:

Equivalence with the Mann-Whitney U test:`library(ROCR)`

`plot(testy@alpha.values[[1]], testy@x.values[[1]], type='n', xlab='Cutoff points of the biomarker', ylab='sensitivity or specificity') lines(testy@alpha.values[[1]], testy@y.values[[1]], type='s', col="#1A425C", lwd=2) lines(testy@alpha.values[[1]], 1-testy@x.values[[1]], type='s', col="#8AB63F", lwd=2) legend(1.15,.85, c('sensitivity', 'specificity'), lty=c(1,1), col=c("#1A425C", "#8AB63F"), cex=.9, bty='n')`

```
wt <-wilcox.test(data=df, df$Biomarker_value ~ df$HCC)
1 - wt$statistic/(sum(df$HCC==1)*sum(df$HCC==0))
```

W 0.40625

```
wt$p.value
```

[1] 0.6828283

- Often, a combination of new markers is selected from a large set. This can result in overoptimistic expectations of the marker’s performance. Any performance measure should be estimated with correction for optimism, for example by applying cross-validation or bootstrap resampling. However, validation in fully independent, external data is the best way to validate a new marker.
- When we want to assess the incremental value of a additional marker (e.g. molecular, genetic, imaging) to an existing model, the increase of the AUC can be reported.

The post Interpretation of the AUC appeared first on Colman Statistics.

]]>The post Comparing methods using a prediction interval appeared first on Colman Statistics.

]]>Est_mean | CI_Lower | CI_Upper | PI_Lower | PI_Upper |
---|---|---|---|---|

140 | 138 | 143 | 113 | 167 |

```
set.seed(123)
hemoglobin<-rnorm(400, mean = 139, sd = 14.75)
df<-data.frame(hemoglobin)
```

Although we don’t need a linear regression yet, I’d like to use the lm() function, which makes it very easy to construct a confidence interval (CI) and a prediction interval (PI). We can estimate the mean by fitting a “regression model” with an intercept only (no slope). The default confidence level is 95%.
-Confidence interval:
```
CI<-predict(lm(df$hemoglobin~ 1), interval="confidence")
CI[1,]
```

## fit lwr upr ## 139.2474 137.8425 140.6524The CI object has a length of 400. But since there is no slope in our “model”, each row is exactly the same. -Prediction interval:

```
PI<-predict(lm(df$hemoglobin~ 1), interval="predict")
```

current data refer to _future_ responses

```
PI[1,]
```

## fit lwr upr ## 139.2474 111.1134 167.3815We get a “warning” that “predictions on current data refer to future responses”. That’s exactly what we want, so no worries there. As you see, the column names of the objects CI and PI are the same. Now, let’s visualize the confidence and the prediction interval. The code below is not very elegant but I like the result (tips are welcome :-))

```
library(ggplot2)
limits_CI <- aes(x=1.3 , ymin=CI[1,2], ymax =CI[1,3])
limits_PI <- aes(x=0.7 , ymin=PI[1,2], ymax =PI[1,3])
PI_CI<-ggplot(df, aes(x=1, y=hemoglobin)) +
geom_jitter(width=0.1, pch=21, fill="grey", alpha=0.5) +
geom_errorbar (limits_PI, width=0.1, col="#1A425C") +
geom_point (aes(x=0.7, y=PI[1,1]), col="#1A425C", size=2) +
geom_errorbar (limits_CI, width=0.1, col="#8AB63F") +
geom_point (aes(x=1.3, y=CI[1,1]), col="#8AB63F", size=2) +
scale_x_continuous(limits=c(0,2))+
scale_y_continuous(limits=c(95,190))+
theme_bw()+ylab("Hemoglobin concentration (g/L)") +
xlab(NULL)+
geom_text(aes(x=0.6, y=160, label="Prediction\ninterval",
hjust="right", cex=2), col="#1A425C")+
geom_text(aes(x=1.4, y=140, label="Confidence\ninterval",
hjust="left", cex=2), col="#8AB63F")+
theme(legend.position="none",
axis.text.x = element_blank(),
axis.ticks.x = element_blank())
PI_CI
```

The width of the confidence interval is very small, now that we have this large sample size (n=400). This is not surprising, as the estimated mean is the only source of uncertainty. In contrast, the width of the prediction interval is still substantial. The prediction interval has two sources of uncertainty: the estimated mean (just like the confidence interval) and the random variance of new observations.
```
Hb<- read.table("http://rforbiostatistics.colmanstatistics.be/wp-content/uploads/2018/06/Hb.txt",
header = TRUE)
head(Hb)
```

New | Reference |
---|---|

84.97 | 87.24 |

99.91 | 103.4 |

111.8 | 116.7 |

117 | 116.7 |

118.1 | 113.5 |

118.2 | 121.7 |

```
plot(Hb$New, Hb$Reference,
xlab="Hemoglobin concentration (g/L) - new method",
ylab="Hemoglobin concentration (g/L) - reference method")
```

```
fit.lm <- lm(Hb$Reference ~ Hb$New)
plot(Hb$New, Hb$Reference,
xlab="Hemoglobin concentration (g/L) - new method",
ylab="Hemoglobin concentration (g/L) - reference method")
cat ("Adding the regression line:")
```

Adding the regression line:
```
abline (a=fit.lm$coefficients[1], b=fit.lm$coefficients[2] )
cat ("Adding the identity line:")
```

Adding the identity line (dotted line):
```
abline (a=0, b=1, lty=2)
```

If both measurement methods would exactly correspond, the intercept would be zero and the slope would be one (=“identity line”, dotted line).
Now let’s calculated the confidence interval for this linear regression.
```
CI_ex <- predict(fit.lm, interval="confidence")
colnames(CI_ex)<- c("fit_CI", "lwr_CI", "upr_CI")
```

And the prediction interval:
```
PI_ex <- predict(fit.lm, interval="prediction")
```

## predictions on current data refer to _future_ responses

```
colnames(PI_ex)<- c("fit_PI", "lwr_PI", "upr_PI")
```

We can combine those results in one dataframe and plot both the confidence interval and the prediction interval
```
Hb_results<-cbind(Hb, CI_ex, PI_ex)
head(Hb_results)
```

New | Reference | fit_CI | lwr_CI | upr_CI | fit_PI | lwr_PI | upr_PI |
---|---|---|---|---|---|---|---|

84.97 | 87.24 | 90.58 | 87.39 | 93.76 | 90.58 | 82.14 | 99.02 |

99.91 | 103.4 | 103.8 | 101.4 | 106.2 | 103.8 | 95.66 | 112 |

111.8 | 116.7 | 114.4 | 112.6 | 116.2 | 114.4 | 106.4 | 122.4 |

117 | 116.7 | 119 | 117.4 | 120.5 | 119 | 111 | 126.9 |

118.1 | 113.5 | 120 | 118.5 | 121.5 | 120 | 112 | 127.9 |

118.2 | 121.7 | 120.1 | 118.6 | 121.6 | 120.1 | 112.1 | 128 |

Visualizing the CI (in green) and the PI (in blue):
```
plot(Hb$New, Hb$Reference,
xlab="Hemoglobin concentration (g/L) - new method",
ylab="Hemoglobin concentration (g/L) - reference method")
Hb_results_s <- Hb_results[order(Hb_results$New),]
lines (x=Hb_results_s$New, y=Hb_results_s$fit_CI)
lines (x=Hb_results_s$New, y=Hb_results_s$lwr_CI,
col="#8AB63F", lwd=1.2)
lines (x=Hb_results_s$New, y=Hb_results_s$upr_CI,
col="#8AB63F", lwd=1.2)
lines (x=Hb_results_s$New, y=Hb_results_s$lwr_PI,
col="#1A425C", lwd=1.2)
lines (x=Hb_results_s$New, y=Hb_results_s$upr_PI,
col="#1A425C", lwd=1.2)
abline (a=0, b=1, lty=2)
```

In (Bland, Altman 2003) it is proposed to calculate the average width of this prediction interval, and see whether this is acceptable.
In the above example, both methods do have the same measurement scale (g/L), but the linear regression with prediction interval is particularly useful when the two methods of measurement have different units.
However, the method has some disadvantages:
- Predictions intervals are very sensitive to deviations from the normal distribution.
- In “standard” linear regression (or Ordinary Least Squares (OLS) regression),the presence of measurement error is allowed for the Y-variable (here, the reference method) but not for the X-variable (the new method). In other words, the absence of errors on the x-axis is one of the assumptions. Since we can expect some measurement error for the new method, this assumption is violated here.

```
library (BivRegBLS)
Hb.BLS = BLS (data = Hb, xcol = c("New"),
ycol = c("Reference"), var.y=10, var.x=8, conf.level=0.95)
XY.plot (Hb.BLS,
yname = "Hemoglobin concentration (g/L) - reference method",
xname = "Hemoglobin concentration (g/L) - new method",
graph.int = c("CI","PI"))
```

Now we would like to decide whether the new method can replace the reference method. We allow the methods to differ up to a given threshold, which is not clinically relevant. Based on this threshold an “acceptance interval” is created.
Suppose that differences up to 10 g/L (=threshold) are not clinically relevant, then the acceptance interval can be defined as Y=X±Δ, with Δ equal to 10.
If the PI is inside the acceptance interval for the measurement range of interest then the two measurement methods can be considered to be interchangeable (see Francq, 2016).
The ```
XY.plot (Hb.BLS,
yname = "Hemoglobin concentration (g/L) - reference method",
xname = "Hemoglobin concentration (g/L) - new method",
graph.int = c("CI","PI"),
accept.int=10)
```

For the measurement region 120g/L to 150 g/L, we can conclude that the difference between both methods is acceptable. If the measurement regions below 120g/l and above 150g/L are important, the new method cannot replace the reference method.
```
Hb_rep <- read.table("http://rforbiostatistics.colmanstatistics.be/wp-content/uploads/2018/06/Hb_rep.txt",
header = TRUE)
head(Hb_rep)
```

New_rep1 | New_rep2 | Ref_rep1 | Ref_rep2 |
---|---|---|---|

88.25 | 94.98 | 90.17 | 84.01 |

109.1 | 109.2 | 106.9 | 98.17 |

114.6 | 122.5 | 116.2 | 118.2 |

120.2 | 114.6 | 114.5 | 104.3 |

108.4 | 110.7 | 116.5 | 108.7 |

125.9 | 124.4 | 112.6 | 112.4 |

When replicates are available, the variance of the measurement errors is calculated for both the new and the reference method, and used to estimate the prediction interval. Again, the BLS() function and the XY.plot() function are used to estimate and plot the BLS regression line, the corresponding CI and PI.
```
Hb_rep.BLS = BLS (data = Hb_rep,
xcol = c("New_rep1", "New_rep2"),
ycol = c("Ref_rep1", "Ref_rep2"),
qx = 1, qy = 1,
conf.level=0.95, pred.level=0.95)
XY.plot (Hb_rep.BLS,
yname = "Hemoglobin concentration (g/L) - reference method",
xname = "Hemoglobin concentration (g/L) - new method",
graph.int = c("CI","PI"),
accept.int=10)
```

It is clear that the prediction interval is not inside the acceptance interval here. The new method cannot replace the reference method. A possible solution is to average repeated measures. The BivRegBLS package can create prediction intervals for the mean of (2 or more) future values, too! More information in ```
plot(x=c(Hb_rep$New_rep1, Hb_rep$New_rep2),
y=c(Hb_rep$Ref_rep1, Hb_rep$Ref_rep2),
xlab="Hemoglobin concentration (g/L) - new method",
ylab="Hemoglobin concentration (g/L) - reference method")
lines (x=as.numeric(Hb_rep.BLS$Pred.BLS[,1]),
y=as.numeric(Hb_rep.BLS$Pred.BLS[,2]),
lwd=2)
lines (x=as.numeric(Hb_rep.BLS$Pred.BLS[,1]),
y=as.numeric(Hb_rep.BLS$Pred.BLS[,3]),
col="#8AB63F", lwd=2)
lines (x=as.numeric(Hb_rep.BLS$Pred.BLS[,1]),
y=as.numeric(Hb_rep.BLS$Pred.BLS[,4]),
col="#8AB63F", lwd=2)
lines (x=as.numeric(Hb_rep.BLS$Pred.BLS[,1]),
y=as.numeric(Hb_rep.BLS$Pred.BLS[,5]),
col="#1A425C", lwd=2)
lines (x=as.numeric(Hb_rep.BLS$Pred.BLS[,1]),
y=as.numeric(Hb_rep.BLS$Pred.BLS[,6]),
col="#1A425C", lwd=2)
abline (a=0, b=1, lty=2)
```

- Although not appropriate in the context of method comparison studies, Pearson correlation is still frequently used. See Bland & Altman (2003) for an explanation on why correlations are not adviced.
- Methods presented in this blogpost are not applicable to time-series

The post Comparing methods using a prediction interval appeared first on Colman Statistics.

]]>The post Taking the baseline measurement into account appeared first on Colman Statistics.

]]>- The delta approach: a comparison of the “delta’s” (post measurement minus baseline measurement) using a independent samples t-test.
- The ANCOVA: A regression model with the pre measurement and group as predictors, and the post measurement as outcome variabele.

- In contrast to the ANCOVA and delta approach, all subjects with at least one measurement (baseline or post-randomization) are included in the analysis.
- The models can easily be extended to 3 or more repeated measures.
- It is possible to model the correlation between baseline and post measures differently for different treatment groups.

```
library(simstudy)
tdef <- defData(varname = "Group", dist = "binary",
formula = 0.5, id = "Id")
tdef <- defData(tdef, varname = "Pre", dist = "normal",
formula = 7, variance = 10)
tdef <- defData(tdef, varname = "Post", dist = "normal",
formula = "Pre + 0.1 + 1.05* Group", variance =3 )
set.seed(123)
dtTrial <- genData(150, tdef)
dtTrial$Group <- factor(dtTrial$Group, levels=c(1,0), labels=c("Exp", "Con"))
library(pander)
pander(head(dtTrial))
```

Group | Pre | Post |
---|---|---|

Con | 10.24 | 10.45 |

Exp | 6.099 | 6.029 |

Con | 3.14 | 1.997 |

Exp | 7.573 | 10.26 |

Exp | 6.561 | 5.952 |

Con | 7.018 | 10.5 |

```
library(ggplot2)
fav.col=c("#1A425C", "#8AB63F")
ggplot(dtTrial, aes (x=Pre,y=Post, col=Group)) +
geom_point() + geom_smooth(method="lm", se=FALSE) +
scale_color_manual(values=fav.col) + theme_bw()
```

```
library (tidyverse)
dtTrial_long <- gather(data=dtTrial, key=Time, value=Outcome,
Pre:Post, factor_key=TRUE)
pander(head(arrange(dtTrial_long, Id), 10))
```

Id | Group | Time | Outcome |
---|---|---|---|

1 | Con | Pre | 10.24 |

1 | Con | Post | 10.45 |

2 | Exp | Pre | 6.099 |

2 | Exp | Post | 6.029 |

3 | Con | Pre | 3.14 |

3 | Con | Post | 1.997 |

4 | Exp | Pre | 7.573 |

4 | Exp | Post | 10.26 |

5 | Exp | Pre | 6.561 |

5 | Exp | Post | 5.952 |

```
library(ggplot2)
boxp <- ggplot (dtTrial_long , aes(x=Time,y=Outcome, col=Group))+
geom_boxplot(outlier.size = 0 ) +
geom_point(aes(fill=Group, col=NULL),shape=21, alpha=0.5,
position = position_jitterdodge(jitter.width = 0.2)) +
scale_fill_manual(values=fav.col) +
scale_color_manual(values=fav.col) +
theme_bw() + xlab("")
boxp
```

```
X <- model.matrix(~ Time * Group, data = dtTrial_long)
colnames(X)
```

```
[1] "(Intercept)" "TimePost" "GroupCon"
[4] "TimePost:GroupCon"
```

```
Xalt <- X[, c("TimePost", "TimePost:GroupCon")]
colnames(Xalt)
```

`[1] "TimePost" "TimePost:GroupCon"`

```
library(nlme)
clda_gls <- gls(Outcome ~ Xalt,
weights = varIdent(form = ~ 1 | Time),
correlation=corSymm (form = ~ 1 | Id),
data = dtTrial_long)
summary(clda_gls)
```

```
Generalized least squares fit by REML
Model: Outcome ~ Xalt
Data: dtTrial_long
AIC BIC logLik
1358.307 1380.47 -673.1537
Correlation Structure: General
Formula: ~1 | Id
Parameter estimate(s):
Correlation:
1
2 0.842
Variance function:
Structure: Different standard deviations per stratum
Formula: ~1 | Time
Parameter estimates:
Pre Post
1.000000 1.059605
Coefficients:
Value Std.Error t-value p-value
(Intercept) 6.978858 0.2461488 28.352190 0e+00
XaltTimePost 1.240246 0.2047301 6.057956 0e+00
XaltTimePost:GroupCon -0.958945 0.2815211 -3.406297 7e-04
Correlation:
(Intr) XltTmP
XaltTimePost -0.129
XaltTimePost:GroupCon 0.000 -0.715
Standardized residuals:
Min Q1 Med Q3 Max
-2.20538393 -0.65214666 -0.09411877 0.63654736 3.40671592
Residual standard error: 3.014695
Degrees of freedom: 300 total; 297 residual
```

`predictions<- cbind( dtTrial_long,clda_gls$fitted)`

The p-value for the interaction effect (the effect of interest here) is 0.0007: the change in mean over time differs significantly between groups. The estimated difference in change is -0.95 (SE: 0.28) (Con increases 0.95 less then Exp).
The estimated correlation between Pre and Post is 0.842. The estimated standard deviation for the Pre measurement is 3.01 and the estimated standard devaition for the Post measurement is 1.059 * 3.01.
We can obtain predicted means using the gls() function. As expected, the predicted value is the same for both groups at baseline ( Id | Group | Time | Outcome | clda_gls$fitted |
---|---|---|---|---|

1 | Con | Pre | 10.24 | 6.979 |

1 | Con | Post | 10.45 | 7.26 |

2 | Exp | Pre | 6.099 | 6.979 |

2 | Exp | Post | 6.029 | 8.219 |

```
library(rms)
clda_Gls <- Gls(Outcome ~ Xalt,
weights = varIdent(form = ~ 1 | Time),
correlation=corSymm (form = ~ 1 | Id),
data = dtTrial_long)
predictions <- cbind(dtTrial_long, predict (clda_Gls, dtTrial_long, conf.int=0.95))
```

Now we do obtain 95% confidence intervals:
Id | Group | Time | Outcome | linear.predictors | lower | upper |
---|---|---|---|---|---|---|

1 | Con | Pre | 10.24 | 6.979 | 6.496 | 7.461 |

1 | Con | Post | 10.45 | 7.26 | 6.684 | 7.836 |

2 | Exp | Pre | 6.099 | 6.979 | 6.496 | 7.461 |

2 | Exp | Post | 6.029 | 8.219 | 7.633 | 8.805 |

```
pd <- position_dodge(.1)
limits <- aes(ymax = upper , ymin=lower, shape=Group)
pCI1 <- ggplot(predictions, aes( y=linear.predictors, x=Time)) +
geom_errorbar(limits, width= 0.1 , position=pd) +
geom_line(aes(group=Group, y=linear.predictors), position=pd) +
geom_point(position=pd, aes( fill=Group), shape=21, size=3) +
scale_fill_manual(values=c( "black", "white")) + theme_bw() +
theme(panel.grid.major = element_blank(), legend.title=element_blank(),
legend.position="bottom") +
xlab(NULL) + ylab("Estimated mean and 95% CI")
pCI1
```

To my opinion, this plot can be misleading. One estimated mean is presented by 2 different dots. I prefer to create the factor ```
predictions$Group2<- factor(predictions$Group, levels= c("All", "Exp", "Con"))
predictions$Group2 [predictions$Time=="Pre"] <- "All"
pd <- position_dodge(.08)
limits <- aes(ymax = upper , ymin=lower, shape=Group2)
pCI <- ggplot(predictions, aes( y=linear.predictors, x=Time)) +
geom_errorbar(limits, width=0.09,position=pd) +
geom_line(aes(group=Group, y=linear.predictors), position=pd)+
geom_point(position=pd, aes( fill=Group2), shape=21, size=3) +
scale_fill_manual(values=c("grey", "black", "white")) + theme_bw() +
theme(panel.grid.major = element_blank(), legend.title=element_blank(),
legend.position="bottom") +
xlab (NULL) + ylab("Estimated mean and 95% CI")
pCI
```

The post Taking the baseline measurement into account appeared first on Colman Statistics.

]]>