Visualizando Resultados de Vários Modelos de Classes Latentes


9

Estou usando a análise de classe latente para agrupar uma amostra de observações com base em um conjunto de variáveis ​​binárias. Estou usando R e o pacote poLCA. No LCA, você deve especificar o número de clusters que deseja encontrar. Na prática, as pessoas geralmente executam vários modelos, cada um especificando um número diferente de classes, e depois usam vários critérios para determinar qual é a "melhor" explicação dos dados.

Costumo achar muito útil examinar os vários modelos para tentar entender como as observações classificadas no modelo com classe = (i) são distribuídas pelo modelo com classe = (i + 1). No mínimo, às vezes você pode encontrar clusters muito robustos que existem, independentemente do número de classes no modelo.

Eu gostaria de uma maneira de representar graficamente esses relacionamentos, de comunicar mais facilmente esses resultados complexos em artigos e de colegas que não são estatisticamente orientados. Imagino que isso seja muito fácil de fazer no R usando algum tipo de pacote simples de rede, mas simplesmente não sei como.

Alguém poderia me apontar na direção certa. Abaixo está o código para reproduzir um exemplo de conjunto de dados. Cada vetor xi representa a classificação de 100 observações, em um modelo com i classes possíveis. Quero representar graficamente como as observações (linhas) se movem de uma classe para outra nas colunas.

x1 <- sample(1:1, 100, replace=T)
x2 <- sample(1:2, 100, replace=T)
x3 <- sample(1:3, 100, replace=T)
x4 <- sample(1:4, 100, replace=T)
x5 <- sample(1:5, 100, replace=T)

results <- cbind (x1, x2, x3, x4, x5)

Imagino que haja uma maneira de produzir um gráfico em que os nós sejam classificações e as bordas reflitam (por pesos ou cor, talvez) a% de observações que passam das classificações de um modelo para o próximo. Por exemplo

insira a descrição da imagem aqui

ATUALIZAÇÃO: Progredindo com o pacote igraph. A partir do código acima ...

Os resultados do poLCA reciclam os mesmos números para descrever a associação à classe, então você precisa recodificar um pouco.

N<-ncol(results) 
n<-0
for(i in 2:N) {
results[,i]<- (results[,i])+((i-1)+n)
n<-((i-1)+n)
}

Então você precisa obter todas as tabulações cruzadas e suas frequências e uni-las em uma matriz definindo todas as arestas. Provavelmente existe uma maneira muito mais elegante de fazer isso.

results <-as.data.frame(results)

g1           <- count(results,c("x1", "x2"))

g2           <- count(results,c("x2", "x3"))
colnames(g2) <- c("x1", "x2", "freq")

g3           <- count(results,c("x3", "x4"))
colnames(g3) <- c("x1", "x2", "freq")

g4           <- count(results,c("x4", "x5"))
colnames(g4) <- c("x1", "x2", "freq")

results <- rbind(g1, g2, g3, g4)

library(igraph)

g1 <- graph.data.frame(results, directed=TRUE)

plot.igraph(g1, layout=layout.reingold.tilford)

insira a descrição da imagem aqui

Hora de jogar mais com as opções de gráficos, eu acho.


11
Se você encontrar uma solução que satisfaça você, também poderá postar seu código como resposta
Gala

2
Isso está se transformando em algo parsets . Veja ggparallel para uma implementação em R.
Andy W

11
Até perceber o comentário do @ Andy, eu pensava em algo como um clustergram (com ID dos sujeitos versus núm . Agrupamentos ) ou talvez um gráfico de fluxo (provavelmente menos atraente se você tiver poucos agrupamentos). Obviamente, isso pressupõe que você esteja disposto a trabalhar no nível individual.
chl

Respostas:


3

Até agora, as melhores opções que encontrei, graças às suas sugestões, são estas:

  library (igraph)
  library (ggparallel)

# Generate random data

  x1 <- sample(1:1, 1000, replace=T)
  x2 <- sample(2:3, 1000, replace=T)
  x3 <- sample(4:6, 1000, replace=T)
  x4 <- sample(7:10, 1000, replace=T)
  x5 <- sample(11:15, 1000, replace=T)
  results <- cbind (x1, x2, x3, x4, x5)
  results <-as.data.frame(results)

# Make a data frame for the edges and counts

  g1           <- count (results, c("x1", "x2"))

  g2           <- count (results, c("x2", "x3"))
  colnames(g2) <- c     ("x1", "x2", "freq")

  g3           <- count (results, c("x3", "x4"))
  colnames(g3) <- c     ("x1", "x2", "freq")

  g4           <- count (results, c("x4", "x5"))
  colnames(g4) <- c     ("x1", "x2", "freq")

  edges        <- rbind (g1, g2, g3, g4)

# Make a data frame for the class sizes

  h1            <- count (results, c("x1"))

  h2            <- count (results, c("x2"))
  colnames (h2) <- c     ("x1", "freq")

  h3            <- count (results, c("x3"))
  colnames (h3) <- c     ("x1", "freq")

  h4            <- count (results, c("x4"))
  colnames (h4) <- c     ("x1", "freq")

  h5            <- count (results, c("x5"))
  colnames (h5) <- c     ("x1", "freq")

  cSizes        <- rbind (h1, h2, h3, h4, h5)

# Graph with igraph

  gph    <- graph.data.frame (edges, directed=TRUE)

  layout <- layout.reingold.tilford (gph, root = 1)
  plot (gph,
        layout           = layout,
        edge.label       = edges$freq, 
        edge.curved      = FALSE,
        edge.label.cex   = .8,
        edge.label.color = "black",
        edge.color       = "grey",
        edge.arrow.mode  = 0,
        vertex.label     = cSizes$x1 , 
        vertex.shape     = "square",
        vertex.size      = cSizes$freq/20)

# The same idea, using ggparallel

  a <- c("x1", "x2", "x3", "x4", "x5")

  ggparallel (list (a), 
              data        = results, 
              method      = "hammock", 
              asp         = .7, 
              alpha       = .5, 
              width       = .5, 
              text.angle = 0)

Feito com igraph

With Igraph

Feito com ggparallel

Com ggparallel

Ainda é muito difícil compartilhar em um diário, mas certamente achei muito útil dar uma olhada nelas.

Também existe uma opção possível dessa pergunta no estouro de pilha , mas ainda não tive a chance de implementá-la; e outra possibilidade aqui .


11
Obrigado por postar os exemplos. Este post no CV mostra um código melhor para os gráficos de ParSets em R (desculpe, deveria ter apontado para isso primeiro). Minha incursão no pacote ggparallel sugere que é bastante difícil até o momento (embora dados aleatórios como você mostre não tendam a parecer bons no IMO para ParSets).
Andy W
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.