mice
: combining inferencesThis is the fifth exercise in the series.
In this exercise we will walk you through different ways of combining inferences based on multiply imputed data sets.
All the best,
1. Open R
and load the following packages and fix the random seed.
library(mice) # Data imputation
library(dplyr) # Data manipulation
library(magrittr) # Flexible piping in R
library(purrr) # Flexible functional programming
set.seed(123)
We choose seed value 123
. This is an arbitrary value; any value would be an equally good seed value. Fixing the random seed enables you (and others) to exactly replicate anything that involves random number generators. If you set the seed in your R
instance to 123
, you will get the exact same results and plots as we present in this document if you follow the order and code of the exercises precisely.
2. Impute the boys
data properly with passive imputation for bmi
with the following parameters:
m = 10
for 10 imputed datasets.maxit = 6
to give the algorithm 6 iterations to obtain a stable solution.print = FALSE
to omit printing of the iteration and imputation history.We will use this data to go through the workflow of data analysis with mids
(multiply imputed data set) objects.
We start by creating the method
vector and specify the passive imputation of bmi
meth <- make.method(boys)
meth["bmi"] <- "~ I(wgt / (hgt / 100)^2)"
Then we remove bmi
as a predictor for hgt
and wgt
to avoid circularity (bmi
feeding back into hgt
and wgt
.
pred <- make.predictorMatrix(boys)
pred[c("hgt", "wgt"), "bmi"] <- 0
pred
## age hgt wgt bmi hc gen phb tv reg
## age 0 1 1 1 1 1 1 1 1
## hgt 1 0 1 0 1 1 1 1 1
## wgt 1 1 0 0 1 1 1 1 1
## bmi 1 1 1 0 1 1 1 1 1
## hc 1 1 1 1 0 1 1 1 1
## gen 1 1 1 1 1 0 1 1 1
## phb 1 1 1 1 1 1 0 1 1
## tv 1 1 1 1 1 1 1 0 1
## reg 1 1 1 1 1 1 1 1 0
and we run the mice
algorithm again with the new predictor matrix (we still ‘borrow’ the imputation methods object meth
from before)
imp <-mice(boys,
meth = meth,
pred = pred,
print = FALSE,
m = 10,
maxit = 6)
We use the multiply imputed data set imp
from now on.
3. Calculate a correlation between all continuous variables for the imputed boys
data
There are two ways in which we can calculate the correlation on the imputed data:
Quite often people are suggesting that using the average imputed dataset - so taking the average over the imputed data set such that any realized cell depicts the average over the corresponding data in the imputed data - would be efficient and conform Rubin’s rules. This is not true. Doing this will yield false inference.
To demonstrate this, let’s ceate the averaged data set and exclude the non-numerical columns:
ave <- imp %>%
mice::complete("long") %>%
group_by(.id) %>%
summarise_all(.funs = mean) %>%
select(-.id, -.imp, -phb, -gen, -reg)
head(ave)
## # A tibble: 6 x 6
## age hgt wgt bmi hc tv
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 0.035 50.1 3.65 14.5 33.7 2.2
## 2 0.038 53.5 3.37 11.8 35 3.3
## 3 0.057 50 3.14 12.6 35.2 2.3
## 4 0.06 54.5 4.27 14.4 36.7 3.7
## 5 0.062 57.5 5.03 15.2 37.3 1.7
## 6 0.068 55.5 4.66 15.1 37 1.9
If we now calculate Pearson’s correlation, rounded to two digits:
cor.wrong <- ave %>%
cor() %>%
round(digits = 2)
we obtain:
cor.wrong
## age hgt wgt bmi hc tv
## age 1.00 0.98 0.95 0.63 0.86 0.86
## hgt 0.98 1.00 0.94 0.60 0.91 0.80
## wgt 0.95 0.94 1.00 0.79 0.84 0.86
## bmi 0.63 0.60 0.79 1.00 0.59 0.64
## hc 0.86 0.91 0.84 0.59 1.00 0.67
## tv 0.86 0.80 0.86 0.64 0.67 1.00
It is best to do a Fisher transformation before pooling the correlation estimates - and a backtransformation afterwards. Therefore we define the following two functions that allow us to transform and backtransform any value:
fisher.trans <- function(x) 1/2 * log((1 + x) / (1 - x))
fisher.backtrans <- function(x) (exp(2 * x) - 1) / (exp(2 * x) + 1)
Now, to calculate the correlation on the imputed data
cor <- imp %>%
mice::complete("all") %>%
map(select, -phb, -gen, -reg) %>%
map(stats::cor) %>%
map(fisher.trans)
cor
## $`1`
## age hgt wgt bmi hc tv
## age Inf 2.1960239 1.838270 0.7334134 1.2838424 1.1631232
## hgt 2.1960239 Inf 1.772436 0.6824682 1.5317094 1.0253561
## wgt 1.8382697 1.7724360 Inf 1.0689689 1.2150216 1.1748799
## bmi 0.7334134 0.6824682 1.068969 Inf 0.6752152 0.7012375
## hc 1.2838424 1.5317094 1.215022 0.6752152 Inf 0.7728062
## tv 1.1631232 1.0253561 1.174880 0.7012375 0.7728062 Inf
##
## $`2`
## age hgt wgt bmi hc tv
## age Inf 2.1910071 1.836386 0.7403549 1.2825782 1.1872138
## hgt 2.1910071 Inf 1.770646 0.6881484 1.5333194 1.0317803
## wgt 1.8363859 1.7706464 Inf 1.0791743 1.2170311 1.2035503
## bmi 0.7403549 0.6881484 1.079174 Inf 0.6812123 0.7323799
## hc 1.2825782 1.5333194 1.217031 0.6812123 Inf 0.7642128
## tv 1.1872138 1.0317803 1.203550 0.7323799 0.7642128 Inf
##
## $`3`
## age hgt wgt bmi hc tv
## age Inf 2.1944834 1.837795 0.7345437 1.2855709 1.1760091
## hgt 2.1944834 Inf 1.771040 0.6824284 1.5347226 1.0140508
## wgt 1.8377948 1.7710398 Inf 1.0711550 1.2192675 1.2097216
## bmi 0.7345437 0.6824284 1.071155 Inf 0.6766605 0.7465336
## hc 1.2855709 1.5347226 1.219267 0.6766605 Inf 0.7633598
## tv 1.1760091 1.0140508 1.209722 0.7465336 0.7633598 Inf
##
## $`4`
## age hgt wgt bmi hc tv
## age Inf 2.1933569 1.832186 0.7383965 1.2794967 1.1604424
## hgt 2.1933569 Inf 1.771422 0.6888356 1.5325723 1.0080486
## wgt 1.8321856 1.7714224 Inf 1.0814855 1.2127519 1.1513295
## bmi 0.7383965 0.6888356 1.081486 Inf 0.6760717 0.6850460
## hc 1.2794967 1.5325723 1.212752 0.6760717 Inf 0.7622345
## tv 1.1604424 1.0080486 1.151329 0.6850460 0.7622345 Inf
##
## $`5`
## age hgt wgt bmi hc tv
## age Inf 2.1987207 1.836872 0.7075307 1.2800161 1.1363762
## hgt 2.1987207 Inf 1.770040 0.6561143 1.5257563 0.9885557
## wgt 1.8368723 1.7700401 Inf 1.0301078 1.2085744 1.1260021
## bmi 0.7075307 0.6561143 1.030108 Inf 0.6454349 0.6516133
## hc 1.2800161 1.5257563 1.208574 0.6454349 Inf 0.7389882
## tv 1.1363762 0.9885557 1.126002 0.6516133 0.7389882 Inf
##
## $`6`
## age hgt wgt bmi hc tv
## age Inf 2.1997805 1.837028 0.7320565 1.2800198 1.1764657
## hgt 2.1997805 Inf 1.774865 0.6841765 1.5250343 1.0380368
## wgt 1.8370278 1.7748650 Inf 1.0703198 1.2176427 1.2172060
## bmi 0.7320565 0.6841765 1.070320 Inf 0.6848232 0.7315825
## hc 1.2800198 1.5250343 1.217643 0.6848232 Inf 0.7739781
## tv 1.1764657 1.0380368 1.217206 0.7315825 0.7739781 Inf
##
## $`7`
## age hgt wgt bmi hc tv
## age Inf 2.1923815 1.837884 0.7329401 1.2744194 1.1944465
## hgt 2.1923815 Inf 1.772881 0.6812806 1.5277814 1.0401921
## wgt 1.8378837 1.7728807 Inf 1.0660449 1.2148237 1.1894146
## bmi 0.7329401 0.6812806 1.066045 Inf 0.6740203 0.6902522
## hc 1.2744194 1.5277814 1.214824 0.6740203 Inf 0.7813761
## tv 1.1944465 1.0401921 1.189415 0.6902522 0.7813761 Inf
##
## $`8`
## age hgt wgt bmi hc tv
## age Inf 2.1977784 1.838968 0.7357619 1.2732988 1.1827927
## hgt 2.1977784 Inf 1.774272 0.6860998 1.5230193 1.0196310
## wgt 1.8389681 1.7742719 Inf 1.0717699 1.2107916 1.1976843
## bmi 0.7357619 0.6860998 1.071770 Inf 0.6783695 0.7342019
## hc 1.2732988 1.5230193 1.210792 0.6783695 Inf 0.7637315
## tv 1.1827927 1.0196310 1.197684 0.7342019 0.7637315 Inf
##
## $`9`
## age hgt wgt bmi hc tv
## age Inf 2.194798 1.839937 0.7240744 1.2705573 1.1647717
## hgt 2.1947979 Inf 1.773808 0.6719150 1.5229541 1.0309059
## wgt 1.8399373 1.773808 Inf 1.0500938 1.2052134 1.1872160
## bmi 0.7240744 0.671915 1.050094 Inf 0.6549673 0.6854105
## hc 1.2705573 1.522954 1.205213 0.6549673 Inf 0.7652942
## tv 1.1647717 1.030906 1.187216 0.6854105 0.7652942 Inf
##
## $`10`
## age hgt wgt bmi hc tv
## age Inf 2.1924482 1.836024 0.7264512 1.2824257 1.1477097
## hgt 2.1924482 Inf 1.773047 0.6762927 1.5330661 1.0060617
## wgt 1.8360237 1.7730470 Inf 1.0574169 1.2184621 1.1541765
## bmi 0.7264512 0.6762927 1.057417 Inf 0.6761177 0.6954423
## hc 1.2824257 1.5330661 1.218462 0.6761177 Inf 0.7733603
## tv 1.1477097 1.0060617 1.154177 0.6954423 0.7733603 Inf
The object cor
is a list over the \(m\) imputations where each listed index is a correlation matrix
. To calculate the average over the correlation matrices, we can add the \(m\) listed indices and divide them by \(m\):
cor.rect <- Reduce("+", cor) / length(cor) # m is equal to the length of the list
cor.rect <- fisher.backtrans(cor.rect)
If we compare the wrong estimates in cor.wrong
cor.wrong
## age hgt wgt bmi hc tv
## age 1.00 0.98 0.95 0.63 0.86 0.86
## hgt 0.98 1.00 0.94 0.60 0.91 0.80
## wgt 0.95 0.94 1.00 0.79 0.84 0.86
## bmi 0.63 0.60 0.79 1.00 0.59 0.64
## hc 0.86 0.91 0.84 0.59 1.00 0.67
## tv 0.86 0.80 0.86 0.64 0.67 1.00
with the correct estimates in cor.rect
round(cor.rect, digits = 2)
## age hgt wgt bmi hc tv
## age NaN 0.98 0.95 0.62 0.86 0.82
## hgt 0.98 NaN 0.94 0.59 0.91 0.77
## wgt 0.95 0.94 NaN 0.79 0.84 0.83
## bmi 0.62 0.59 0.79 NaN 0.59 0.61
## hc 0.86 0.91 0.84 0.59 NaN 0.64
## tv 0.82 0.77 0.83 0.61 0.64 NaN
We see that the wrong estimates in cor.wrong
have the tendency to overestimate the correlation coefficient that is correctly combined following Rubin’s rules.
The correct estimates have a diagonal of NaN
’s, because the tranformation of a correlation of 1
yields Inf
and the backtransformation of Inf
has no representation in real number space. We know the diagonal is supposed to be 1, so we can simply correct this
diag(cor.rect) <- 1
cor.rect
## age hgt wgt bmi hc tv
## age 1.0000000 0.9755061 0.9505194 0.6234031 0.8562776 0.8239305
## hgt 0.9755061 1.0000000 0.9438769 0.5913737 0.9102522 0.7699732
## wgt 0.9505194 0.9438769 1.0000000 0.7874385 0.8378628 0.8278038
## bmi 0.6234031 0.5913737 0.7874385 1.0000000 0.5864837 0.6077652
## hc 0.8562776 0.9102522 0.8378628 0.5864837 1.0000000 0.6445590
## tv 0.8239305 0.7699732 0.8278038 0.6077652 0.6445590 1.0000000
In FIMD v2
, paragraph 5.1.2 Stef mentions the following:
The average workflow is faster and easier than the correct methods, since there is no need to replicate the analyses \(m\) times. In the words of Dempster and Rubin (1983), this workflow is
seductive because it can lull the user into the pleasurable state of believing that the data are complete after all.
The ensuing statistical analysis does not know which data are observed and which are missing, and treats all data values as real, which will underestimate the uncertainty of the parameters. The reported standard errors and p-values after data-averaging are generally too low. The correlations between the variables of the averaged data will be too high. For example, the correlation matrix in the average data are more extreme than the average of the \(m\) correlation matrices, which is an example of ecological fallacy. As researchers tend to like low p-values and high correlations, there is a cynical reward for the analysis of the average data. However, analysis of the average data cannot give a fair representation of the uncertainties associated with the underlying data, and hence is not recommended.
So, please stay away from averaging the imputed data sets. Instead, use the correct workflow of analyzing the imputed sets seperately and combining the inference afterwards.
4. Fit the following linear model on the imputed data:
lm(age ~ wgt + hgt)
fit1.lm <- imp %>%
with(lm(age ~ wgt + hgt))
est1.lm <- pool(fit1.lm)
est1.lm
## Class: mipo m = 10
## term m estimate ubar b t dfcom
## 1 (Intercept) 10 -7.48484461 5.891627e-02 1.727421e-04 5.910628e-02 745
## 2 wgt 10 0.07227995 3.478153e-05 2.500248e-07 3.505655e-05 745
## 3 hgt 10 0.10645255 1.089061e-05 6.405888e-08 1.096107e-05 745
## df riv lambda fmi
## 1 739.9900 0.003225194 0.003214825 0.005897997
## 2 733.4812 0.007907280 0.007845246 0.010539557
## 3 735.7374 0.006470233 0.006428638 0.009118555
summary(est1.lm)
## term estimate std.error statistic df p.value
## 1 (Intercept) -7.48484461 0.243117839 -30.78690 739.9900 0
## 2 wgt 0.07227995 0.005920857 12.20768 733.4812 0
## 3 hgt 0.10645255 0.003310751 32.15360 735.7374 0
5. Now expand the linear model from (4) with a squared term for hgt
:
lm(age ~ wgt + hgt + I(hgt^2))
fit2.lm <- imp %>%
with(lm(age ~ wgt + hgt + I(hgt^2)))
est2.lm <- pool(fit2.lm)
est2.lm
## Class: mipo m = 10
## term m estimate ubar b t dfcom
## 1 (Intercept) 10 -4.0401500544 2.481985e-01 4.533153e-04 2.486972e-01 744
## 2 wgt 10 0.0312162871 5.970293e-05 3.323328e-07 6.006850e-05 744
## 3 hgt 10 0.0386114111 8.520263e-05 2.418903e-07 8.546871e-05 744
## 4 I(hgt^2) 10 0.0003604169 2.120409e-09 6.822827e-12 2.127914e-09 744
## df riv lambda fmi
## 1 740.2754 0.002009065 0.002005036 0.004690434
## 2 735.2608 0.006123084 0.006085820 0.008778403
## 3 739.1093 0.003122900 0.003113178 0.005799809
## 4 738.6361 0.003539464 0.003526980 0.006214209
summary(est2.lm)
## term estimate std.error statistic df p.value
## 1 (Intercept) -4.0401500544 4.986955e-01 -8.101437 740.2754 2.220446e-15
## 2 wgt 0.0312162871 7.750387e-03 4.027707 735.2608 6.217697e-05
## 3 hgt 0.0386114111 9.244929e-03 4.176496 739.1093 3.313683e-05
## 4 I(hgt^2) 0.0003604169 4.612932e-05 7.813186 738.6361 1.909584e-14
6. Compare the models from (4) and (5) to see which model would yield the best fit:
We have three choices for evaluation:
D1(fit2.lm, fit1.lm) # multivariate Wald test
## test statistic df1 df2 dfcom p.value riv
## 1 ~~ 2 61.04588 1 739.7552 744 1.909584e-14 0.003539464
The \(D_1\) statistic requires a variance covariance matrix for the estimates.
D2(fit2.lm, fit1.lm) # combining test statistics
## test statistic df1 df2 dfcom p.value riv
## 1 ~~ 2 60.99329 1 466721.9 NA 5.77316e-15 0.004410659
The \(D_2\) requires only the test statistics (e.g. p-values or \(X^2\) values) and hence is more flexible to apply than the \(D_1\) statistic: But this comes at a cost as the resulting inference is less informed by the data than under the \(D_1\) statistic.
D3(fit2.lm, fit1.lm) # likelihood ratio test
## test statistic df1 df2 dfcom p.value riv
## 1 ~~ 2 58.99007 1 268897.9 744 1.587619e-14 0.003368425
For large sample size, \(D_3\) is equivalent to \(D_1\), however, \(D_3\) does not require the covariances of the complete data estimates. It is the preferred method for testing random effects, and connects to global fit statistics in structural equation models. The likelihood ratio test does not require normality. For large riv
(i.e. values > 10), the \(D_3\) statistics must be taken with a grain of salt. In general, given what we know today, the \(D_1\) statistic may be slightly more efficient than \(D_3\) for small samples (i.e. \(< 200\) cases); for larger samples (i.e. \(\geq 200\) cases) the \(D_1\) and \(D_3\) appear equally good and a choice between them is mostly a matter of convenience –> see also paragraph 5.3.4 in FIMD v2
for a comparison on when to use \(D_1\), \(D_2\) and/or \(D_3\).
7. Fit a stepwise linear model to predict hgt
seperately to each of the imputed data sets.
We can use the step()
function in R
to select formula-based models. We start by specifying the scope of the evaluations:
scope <- list(upper = ~ age + wgt + hc + gen + phb + tv + reg,
lower = ~ 1)
The scope specifies the upper bound of the model (all variable to run the selection on) and lower bound of the mode, where a 1
indicates an intercept only model.
We can then specify the expressions to be evaluated:
expr <- expression(f1 <- lm(hgt ~ 1),
f2 <- step(f1,
scope = scope,
direction = "forward",
trace = 0
))
where f1
is the linear model to be evaluated and f2
the step()
function that evaluates the f1
function. Finally, we apply the with()
function to evaluate the expression expr
on object imp
:
fit <- with(imp, expr)
The fit
object contains the model evaluations To calculate the times each variable was selected, we can run:
formulas <- lapply(fit$analyses, formula)
terms <- lapply(formulas, terms)
votes <- unlist(lapply(terms, labels))
table(votes)
## votes
## age gen hc phb reg tv wgt
## 10 3 10 10 1 6 10
We see that reg
is only used in 1 models based on the 10 imputed datasets. tv
is used in 6 of the models and gen
is used in 3 of the 10 completed-data models. wgt
, hc
, age
and phb
are used in all models.
To determine if gen
should be a part of the final model, we may run a multivariate Wald test:
fit.gen <- with(imp, lm(hgt ~ age + hc + phb + wgt + gen))
fit.nogen <- with(imp, lm(hgt ~ age + hc + phb + wgt))
D1(fit.gen, fit.nogen)
## test statistic df1 df2 dfcom p.value riv
## 1 ~~ 2 1.086821 4 168.946 735 0.3647302 0.5946789
With a p-value of .059
we could conclude that gen
is not strictly needed in this model. We might also investigate the BIC on the seperate imputed sets and compare those across (not within) models. We draw the same conclusion from this evaluation - the BIC is lower for the model without gen
- although not by much. But then again, the p-value indicated the same trend.
BIC.gen <- fit.gen$analyses %>%
sapply(BIC)
BIC.nogen <- fit.nogen$analyses %>%
sapply(BIC)
To count the model evaluations in favor of BIC.nogen
–> better fit means lower BIC:
BIC.gen
## [1] 5119.745 5096.645 5122.573 5063.054 5123.554 5083.536 5084.813 5102.367
## [9] 5068.139 5109.723
BIC.nogen
## [1] 5099.175 5081.218 5098.136 5057.492 5106.433 5072.734 5060.464 5081.877
## [9] 5047.834 5096.033
sum(BIC.gen > BIC.nogen)
## [1] 10
Please not that we can compare the BIC only over the models, not over the imputed data sets. The realized imputations differ for each set, but for each imputed set, the model comparison is based on the same realization. The sum(BIC.gen > BIC.nogen)
compares only the BIC’s against its counterpart for the same imputed data set. The resulting outcome can be considered as a majority vote: in our case 10 out of 10 model comparisons are in favor of the model without gen
as a predictor.
8. Calculate the average mean for bmi
for every region reg
over the imputed data.
To study the means for bmi
conditionally on reg
to get a picture of what the differences are:
imp %>%
mice::complete("long") %>%
select(reg, bmi) %>%
group_by(reg) %>%
summarise_all(.funs = mean)
## # A tibble: 5 x 2
## reg bmi
## <fct> <dbl>
## 1 north 19.3
## 2 east 17.9
## 3 west 17.9
## 4 south 17.7
## 5 city 18.2
To also obtain information about the standard error of the mean, we could extend the summarise_all()
evaluation wit a custom standard error function:
se <- function(x){
sd(x) / sqrt(length(x))
}
and then calculate the summary again
imp %>%
mice::complete("long") %>%
select(reg, bmi) %>%
group_by(reg) %>%
summarise_all(list(~ mean(.), ~se(.)))
## # A tibble: 5 x 3
## reg mean se
## <fct> <dbl> <dbl>
## 1 north 19.3 0.120
## 2 east 17.9 0.0742
## 3 west 17.9 0.0603
## 4 south 17.7 0.0698
## 5 city 18.2 0.0978
9. Test whether the means differ.
This is best done with an ANOVA. To do this correctly, we can apply the following workflow. First, we fit an intercept only model
fit.empty <- imp %>%
mice::complete("all") %>%
map(lm, formula = bmi ~ 1)
and then we fit the model with reg
as a predictor
fit.reg <- imp %>%
mice::complete("all") %>%
map(lm, formula = bmi ~ 1 + reg)
We can calculate the seperate ANOVA’s from each fitted model:
aov.empty <- lapply(with(imp, lm(age ~ 1))$analyses, aov)
aov.reg <- lapply(with(imp, lm(age ~ 1 + reg))$analyses, aov)
And look at the summaries:
lapply(aov.empty, summary)
## [[1]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[2]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[3]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[4]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[5]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[6]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[7]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[8]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[9]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
##
## [[10]]
## Df Sum Sq Mean Sq F value Pr(>F)
## Residuals 747 35503 47.53
The summary for the aov.empty
object has no p-values. This is expected as we are fitting an empty model (without any predictors) and hence have no model Mean Squares (MS) to calculate and test the ratio
\[F = \frac{\text{Model MS}}{\text{Residual MS}}\]
We do have those components for the model with reg
included as predictor:
lapply(aov.reg, summary)
## [[1]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 745 186.37 3.984 0.00332 **
## Residuals 743 34758 46.78
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[2]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 691 172.71 3.686 0.00556 **
## Residuals 743 34813 46.85
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[3]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 757 189.21 4.046 0.00298 **
## Residuals 743 34747 46.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[4]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 750 187.61 4.011 0.00316 **
## Residuals 743 34753 46.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[5]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 756 188.94 4.04 0.00301 **
## Residuals 743 34748 46.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[6]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 750 187.49 4.008 0.00318 **
## Residuals 743 34753 46.77
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[7]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 762 190.60 4.076 0.00282 **
## Residuals 743 34741 46.76
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[8]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 695 173.84 3.711 0.00533 **
## Residuals 743 34808 46.85
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[9]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 757 189.36 4.049 0.00296 **
## Residuals 743 34746 46.76
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## [[10]]
## Df Sum Sq Mean Sq F value Pr(>F)
## reg 4 744 185.99 3.976 0.00337 **
## Residuals 743 34759 46.78
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
We find that each of the seperate ANOVA’s indicates significance, meaning that there is an overall effect for reg
on bmi
in each imputed data set.
To obtain an overall estimate for the ANOVA we can simply compare the empty model to the model with reg
included:
D1(fit.reg, fit.empty)
## test statistic df1 df2 dfcom p.value riv
## 1 ~~ 2 4.504619 4 735.114 743 0.001334955 0.01786418
And find that indeed the overall (i.e. pooled) effect over the imputations is also significant, which is not surprising as the F-values for the seperate tests show little variation.
- End of exercise