3
$\begingroup$

I have a longitudinal database that has more than 50% of the missing data of the MAR type.

This amount of missing values was a surprise to me because I did not foresee this in the study design, and for that reason I cannot delete those that have missing values because my sample N will be very small. however, these imputation methods are new to me, and I am facing many difficulties.

I saw some tutorials on multiple imputation through the MICE package. So the following points were not clear:

How to specify categorical variables (The categorical variables have no missing data). In my case I have two categorical variables, one with two levels (before and after) and the other with 4 levels (grp1,grp2, grp3, grp4). and eight continuous variables with missing values (D0 to D7).

Just like in the example below:

enter image description here

When imputing data I would like to specify that an imputation should occur through categorical variables (time and group).

I used the code below but I don't know if considered the categorical variables

 library(mice)
 imputed_Data <- mice (my.data, m = 5, maxit = 50, method = 'pmm', seed = 500)
 

After making the imputations, I would like to change from the wide format to the long format, where there would be only the columns: ID, Name, Time, group and a two columns one with the repeated mensure (D0 to D6) and other with Values. I know how to do this with DAtaFrames, but the object generated by mice is of the mids type. As in the example below:

![enter image description here

As my data are repeated (dependent) measures, I want to perform the analysis of generalized equation estimation.

fit<- with(geeglm(value ~ Time+ group,
              data= IM.imputed_Data ,family=gaussian,id=ID,
              corstr="ar1"))


  summary(pool(fit))
$\endgroup$

3 Answers 3

3
$\begingroup$

There are two ways to do this in the mice package. First, you could use complete() to turn the imputed mids object into a dataframe containing the impute values, reshape the dataframe into long format, turn it into a new mids object with as.mids(), then fit the models with the new mids object. Second, you could place the code to reshape the data inside the with() block. I show an example of how to do that below

library(geepack)
library(mice)
#> 
#> Attaching package: 'mice'
#> The following object is masked from 'package:stats':
#> 
#>     filter
#> The following objects are masked from 'package:base':
#> 
#>     cbind, rbind
library(tidyverse)
# This data comes in long format and has no missing values, so I
# first transform it to wide and make some values missing
koch2 <- koch
koch2$id <- factor(koch2$id)
koch2$trt <- factor(koch2$trt)
koch2 <- pivot_wider(koch2,
                     names_from = day,
                     values_from = y,
                     names_prefix = "day")
set.seed(1)
koch2[rbinom(nrow(koch2),1,0.1)==1, "day3"] <- NA
koch2[rbinom(nrow(koch2),1,0.1)==1, "day7"] <- NA
koch2[rbinom(nrow(koch2),1,0.1)==1, "day10"] <- NA
koch2[rbinom(nrow(koch2),1,0.1)==1, "day14"] <- NA
# Create imputations, using predictorMatrix to specify the
# variables used in imputations
ini <- mice(koch2,
            maxit = 0)
pred <- ini$predictorMatrix
pred[,"id"] <- 0
imp_dat <- mice(koch2,
                printFlag = FALSE,
                predictorMatrix = pred)
# fit the models to the imputed data
mods <- with(imp_dat,
             {
               dat <- data.frame(trt = trt,
                                 id = id,
                                 day3 = day3,
                                 day7 = day7,
                                 day10 = day10,
                                 day14 = day14)
               dat_long <- pivot_longer(dat,
                                        cols = contains("day"),
                                        names_to = "time",
                                        values_to = "y")
               geeglm(y ~ time + trt,
                      id = id,
                      data = dat_long)
             })
summary(pool(mods))
#>          term   estimate  std.error  statistic       df      p.value
#> 1 (Intercept)  2.0861111 0.09938558 20.9900775 259.9958 0.000000e+00
#> 2   timeday14 -0.3055556 0.09866652 -3.0968514 264.0978 2.166670e-03
#> 3    timeday3  0.4500000 0.07020265  6.4100143 118.7481 3.066805e-09
#> 4    timeday7  0.0500000 0.08668541  0.5767983 196.6644 5.647353e-01
#> 5        trt1 -0.3444444 0.10217856 -3.3710051 250.4968 8.672982e-04

If there are many variables in the imputed data, you can select all of them using dat <- data.frame(mget(ls())). If you only want some of the variables, the ls() could be replaced with a vector of character names of variables, which could be generated programmatically.

To use the complete() method I initially mentioned you need to set include = TRUE and also recalculate the .id column created by mice. Below is an example of how to do that.

all_dats <- complete(imp_dat, action = "long", include = TRUE)
working_dats <- list()
for(i in 0:max(all_dats$.imp)) {
  working_dats[[i+1]] <- 
    all_dats %>%
    subset(.imp == i) %>%
    pivot_longer(cols = contains("day"),
                 names_to = "time",
                 values_to = "y") %>%
    mutate(.id = 1:nrow(.))
}
imputed_long <- as.mids(do.call(rbind, working_dats))
mods_complete <- with(imputed_long,
                      geeglm(y ~ time + trt,
                             id = id))
summary(pool(mods_complete))
#>          term   estimate  std.error  statistic       df      p.value
#> 1 (Intercept)  2.0861111 0.09938558 20.9900775 259.9958 0.000000e+00
#> 2   timeday14 -0.3055556 0.09866652 -3.0968514 264.0978 2.166670e-03
#> 3    timeday3  0.4500000 0.07020265  6.4100143 118.7481 3.066805e-09
#> 4    timeday7  0.0500000 0.08668541  0.5767983 196.6644 5.647353e-01
#> 5        trt1 -0.3444444 0.10217856 -3.3710051 250.4968 8.672982e-04
$\endgroup$
2
  • $\begingroup$ The with() method that you show works for me. However, I cannot get the complete(...) %>% pivot_longer(...) %>% as.mids() approach to work; I get an error about duplicate row.names. I also want to ask, within the with() method, is there a more convenient way to create dat than to manually add each column one by one? My data frame has a lot of columns so that is a tedious task. $\endgroup$ Commented Jun 16, 2021 at 21:40
  • 1
    $\begingroup$ @LC-datascientist I added example code for complete(). You can use data.frame(mget(ls())) to get all columns that were in the imputed data. $\endgroup$ Commented Jun 17, 2021 at 22:14
0
$\begingroup$

You could use tidyr::gather() to transform your data into long format and then use the package jomo for multiple imputation accounting for the nested structure of the data.

$\endgroup$
6
  • $\begingroup$ I tried to use ´gather´but the object generated by mice is of the mids type, and gather did not work. $\endgroup$ Commented Mar 29, 2021 at 13:50
  • $\begingroup$ Sorry, I meant using gather() first. Once you have the data in long format, then proceed to imputing. $\endgroup$
    – teamug
    Commented Mar 29, 2021 at 18:01
  • $\begingroup$ teamug I thought that to use mice the variables should be in columns (Wide format) .. I will try it like this. $\endgroup$ Commented Mar 29, 2021 at 19:13
  • $\begingroup$ That is probably true, but if you want to proceed in long format, jomo can handle it, and specifying the cluster is pretty straightforward. $\endgroup$
    – teamug
    Commented Mar 30, 2021 at 5:56
  • $\begingroup$ Okay, the jomo package is new to me so I research it to understand it better. I don't know if I will have enough time, but I will try. $\endgroup$ Commented Mar 30, 2021 at 13:33
0
$\begingroup$

Have you tried the following:

fit<- with(imputed_Data, geeglm(value ~ Time+ group,
              family=gaussian,id=ID,
              corstr="ar1"))


summary(pool(fit))
$\endgroup$
1
  • 1
    $\begingroup$ ,I did a test with other data that I have and it worked, but with my data it is not working because I couldn't change from wide format to long $\endgroup$ Commented Mar 29, 2021 at 17:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.