---
title: "Multinomial Latent Regression"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Multinomial Latent Regression}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```


1. Timepoints: T=1
2. Latent Classes: K=2, 2^K = 4 latent classes
3. Recover latent regression parameters and check classification accuracy 


## Specify Details of Data Generation 
First step is to set-up the data we will be generating. Here 1,000 subjects from 4 different latent classes responded to 16 items. Data was only collected once.  
```{r Specify}

library(CLCM)
library(nnet)
N <- 1000
number.timepoints <- 1
item.type <- rep( c('Ordinal', 'Nominal', 'Poisson', 'Neg_Binom', 'ZINB', 'ZIP', 'Normal', 'Beta'), 2)
sim.categories.j <- rep( c(4, 4, 30, 30, 30, 30, NA, NA) , 2)
J <- length(item.type)
item.names <- paste0('Item_', 1:J)
K= 2
Q <- matrix(c(rep(c(1,0), J/2), rep(c(0, 1), J/2)), nrow = J, ncol = K, byrow = TRUE)

```


### Subject Posterior Distributions via Multinomial Regression 

Generate the subject posteriors via (multinomial) latent regression. The latent class assignments will differ across the two observed groups (`Group`). 

```{r Generate_1}
set.seed(09092026)
number.groups <- 2
dat <- data.frame(
  'USUBJID' = rep(paste0('Subject_', formatC(1:N, width = 4, flag = '0')), length.out= N*number.timepoints),
  'Group' = rep(paste0('Group_', 1:number.groups), length.out = N*number.timepoints),
  'Time' = rep(paste0('Time_', 1:number.timepoints), each = N),
  stringsAsFactors=FALSE)
# Design Matrix
XX <- model.matrix( ~ Group, data = dat) 
# Beta
Beta <- matrix(0, nrow = ncol(XX), ncol = 2^K - 1, dimnames=list(colnames(XX), rep('LC', 2^K -1)))
Beta[1, ] <- c(0.2, 0.8, 0.4)
Beta[2, ] <- c(0.2, -1.0, -1.6)
Beta

# Matrix multiply:
XB <- XX %*% Beta
p <- exp(XB)/(1 + apply(exp(XB), 1, sum))
p <-  cbind(1 - rowSums(p), p)
lca <-  vector()
for(i in 1:nrow(p)){
  lca <- c(lca, 
           sample(x = c(1:(2^K)), size = 1, prob = p[i, ])  
  )
} #end loop to sample lca

```

At this point we have used the observed group membership (`Group`) to generate the (true) posterior distributions/latent class assignments for both timepoints. Let's check the latent class assignments vs Observed group assignment. Again, we haven't yet moved into latent class models yet. 

```{r Generate_2}
# Check the LCA 
prop.table(table(lca))
# Check LCA across observed Groups:
prop.table(xtabs( ~ lca + dat$Group), margin = 1)
      
```


Before we move on with the simulation, let's just do a quick check on whether a simple multinomial logistic regression can recover this. Regress latent class assignment onto observed groups:

```{r Generate_3}

mod <- multinom(as.factor(lca) ~ dat$Group)
coef(mod)
t(Beta)

```

Recovery seems fine. Let's create the true posterior distributions and pass to the simulation function.

## Simulate Item Responses
```{r Generate_4}

post <- matrix(0, nrow = nrow(dat), ncol = 2^K)
post[ cbind(1:nrow(dat), lca) ] <- 1 

set.seed(03062021)
X <- simulate_clcm(N = N, number.timepoints = number.timepoints, 
                   Q = Q, 
                   item.names = item.names, 
                   item.type = item.type, 
                   categories.j = sim.categories.j, 
                   post = post)

```


Merge the dataframe with the Observed Group membership with the simulated dataframe. You need the `Group` variable with the item responses to pass to the model estimation function. If you don't, the estimation routine won't have a `Group` variable to compute the multinomial latent regression with. 

```{r Generate_5}
dat.cov <- merge(x = dat, y = X$dat, by = c('USUBJID', 'Time'))
```

Specify the latent regression formula - regress latent classes onto `Group` variable in model estimation by passing `lat.reg = list('Time_1' = 'Group')`. Note: if we had additional covariates, we would pass the corresponding regression formula, e.g. `'Group + Sex + Age'`. This will be passed to `as.formula` and then passed to a function that fits a regression.

## Estimate CLCM

```{r Estimate}

mod <- clcm(dat = dat.cov, 
            item.type = item.type, 
            item.names = item.names, 
            Q = Q, max.diff = 0.001, 
            lat.reg = list('Time_1' = 'Group') )    

```


## Results


Evaluate the Latent Regression Parameters:
```{r Results}

Beta # Generating parameter
mod$lat.reg.param  # estimate

```


Next, compare true classification (latent class assignment, lca) with estimates:
```{r Classification}
lca.hat <- mod$dat$lca 
lca.true <- apply( dat.cov[ , grep('true_post', colnames(dat.cov)) ], 1, which.max)
xtabs( ~ lca.hat + lca.true)
table(lca.true == lca.hat)
prop.table(table(lca.true == lca.hat))

```


Confirmed. 