How to de-aggregate binomial response data from individuals with the same covariates to bernoulli and vice-versa?

Viewed 224

I want to implement binary logistic regression using binomial data as discussed here. Additionally, I want to add a variable that identifies each binary data point coming from de-aggregation of the same binomial data point, so that I can properly account for their correlation in the analysis.

Below I present the outcome of my attempts so far. It successfully replicates the rows with respective covariates, but does not generate the binary variable yet. Any help would be much appreciated.

#Structure of input binomial data#

DT<-tibble::tibble(Successes = c(2,3,3), Trials=c(3,4,5), X1=c("Yes", "No", "Yes"), X2=c(10.7, 11.3, 9.9))
# A tibble: 3 x 4
  Successes Trials X1       X2
      <dbl>  <dbl> <chr> <dbl>
         2      3 Yes    10.7
         3      4 No     11.3
         3      5 Yes     9.9

#My attempts so far#

DT.expanded <- DT[rep(seq(nrow(DT)), DT$Trials), ]

DT.expanded
# A tibble: 12 x 4
   Successes Trials X1       X2
       <dbl>  <dbl> <chr> <dbl>
          2      3 Yes    10.7
          2      3 Yes    10.7
          2      3 Yes    10.7
          3      4 No     11.3
          3      4 No     11.3
          3      4 No     11.3
          3      4 No     11.3
          3      5 Yes     9.9
          3      5 Yes     9.9
          3      5 Yes     9.9
          3      5 Yes     9.9
          3      5 Yes     9.9

#Expected structure of output binary data#

# A tibble: 12 x 4
    Success   X1       X2
       <chr>  <chr> <dbl>
         1    Yes    10.7
         1    Yes    10.7
         0    Yes    10.7
         1    No     11.3
         1    No     11.3
         1    No     11.3
         0    No     11.3
         1    Yes     9.9
         1    Yes     9.9
         1    Yes     9.9
         0    Yes     9.9
         0    Yes     9.9

Thanks in advance for any help.

2 Answers

For this sort of expansion, I find it's easiest to generate a list column, where the list element for each row is a binary vector for that row, which you can create with c and rep for the appropriate number of 0s and 1s. Once you've got a list column, you can expand the data frame to fit. For example,

library(tidyverse)

df <- tibble(
    Successes = c(2,3,3), 
    Trials = c(3,4,5), 
    X1 = c("Yes", "No", "Yes"), 
    X2 = c(10.7, 11.3, 9.9)
)

df <- df %>% mutate(binary = map2(Successes, Trials, 
                                  ~ c(rep(1, .x), 
                                      rep(0, .y - .x))))
df
#> # A tibble: 3 x 5
#>   Successes Trials X1       X2 binary   
#>       <dbl>  <dbl> <chr> <dbl> <list>   
#> 1         2      3 Yes    10.7 <dbl [3]>
#> 2         3      4 No     11.3 <dbl [4]>
#> 3         3      5 Yes     9.9 <dbl [5]>

df2 <- df %>% unnest()
df2
#> # A tibble: 12 x 5
#>    Successes Trials X1       X2 binary
#>        <dbl>  <dbl> <chr> <dbl>  <dbl>
#>  1         2      3 Yes    10.7      1
#>  2         2      3 Yes    10.7      1
#>  3         2      3 Yes    10.7      0
#>  4         3      4 No     11.3      1
#>  5         3      4 No     11.3      1
#>  6         3      4 No     11.3      1
#>  7         3      4 No     11.3      0
#>  8         3      5 Yes     9.9      1
#>  9         3      5 Yes     9.9      1
#> 10         3      5 Yes     9.9      1
#> 11         3      5 Yes     9.9      0
#> 12         3      5 Yes     9.9      0

An approach using data.table and replace:

library(data.table)
setDT(DT)
DT[, .(Success=replace(rep(0L, Trials), seq_len(Successes), 1L), 
       X1, X2), 
    by=seq_len(DT[,.N])][, -1L]

output:

    Success  X1   X2
 1:       1 Yes 10.7
 2:       1 Yes 10.7
 3:       0 Yes 10.7
 4:       1  No 11.3
 5:       1  No 11.3
 6:       1  No 11.3
 7:       0  No 11.3
 8:       1 Yes  9.9
 9:       1 Yes  9.9
10:       1 Yes  9.9
11:       0 Yes  9.9
12:       0 Yes  9.9
Related