Visualizzazione dei risultati da più modelli di classe latenti


9

Sto usando l'analisi di classe latente per raggruppare un campione di osservazioni basate su una serie di variabili binarie. Sto usando R e il pacchetto poLCA. In LCA, è necessario specificare il numero di cluster che si desidera trovare. In pratica, le persone di solito eseguono diversi modelli, ognuno dei quali specifica un diverso numero di classi e quindi utilizza vari criteri per determinare quale sia la "migliore" spiegazione dei dati.

Trovo spesso molto utile guardare attraverso i vari modelli per cercare di capire come le osservazioni classificate nel modello con class = (i) sono distribuite dal modello con class = (i + 1). Per lo meno, a volte puoi trovare cluster molto robusti che esistono indipendentemente dal numero di classi nel modello.

Vorrei un modo per rappresentare graficamente queste relazioni, per comunicare più facilmente questi risultati complessi nei documenti e ai colleghi che non sono orientati statisticamente. Immagino che sia molto facile farlo in R usando una sorta di semplice pacchetto grafico di rete, ma semplicemente non so come.

Qualcuno potrebbe indicarmi la giusta direzione. Di seguito è riportato il codice per riprodurre un set di dati di esempio. Ogni vettore xi rappresenta la classificazione di 100 osservazioni, in un modello con i possibili classi. Voglio rappresentare graficamente come le osservazioni (righe) si spostano da una classe all'altra attraverso le colonne.

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)

Immagino che ci sia un modo per produrre un grafico in cui i nodi sono classificazioni e i bordi riflettono (in base al peso o forse al colore) la percentuale di osservazioni che si spostano da classificazioni da un modello a quello successivo. Per esempio

inserisci qui la descrizione dell'immagine

AGGIORNAMENTO: Avere qualche progresso con il pacchetto igraph. A partire dal codice sopra ...

I risultati di poLCA riciclano gli stessi numeri per descrivere l'appartenenza alla classe, quindi devi fare un po 'di ricodifica.

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

Quindi è necessario ottenere tutte le tabulazioni incrociate e le relative frequenze e raggrupparle in una matrice che definisca tutti i bordi. C'è probabilmente un modo molto più elegante per farlo.

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)

inserisci qui la descrizione dell'immagine

È ora di giocare di più con le opzioni di igraph immagino.


1
Se trovi una soluzione che ti soddisfa, puoi anche pubblicare il tuo codice come risposta
Gala

2
Questo si sta trasformando in qualcosa di simile ai parset . Vedi ggparallel per un'implementazione R.
Andy W,

1
Fino a quando non ho notato il commento di @ Andy, stavo pensando a qualcosa di simile a un clustergram (con ID dei soggetti vs. cluster n.) O forse a uno streamgraph (probabilmente meno attraente se hai pochi cluster). Questo, ovviamente, presuppone che tu sia disposto a lavorare a livello individuale.
chl

Risposte:


3

Finora, le migliori opzioni che ho trovato, grazie ai tuoi suggerimenti, sono queste:

  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)

Fatto con igraph

Con Igraph

Fatto con ggparallel

Con ggparallel

Ancora troppo difficile da condividere in un diario, ma ho sicuramente trovato molto utile dare un'occhiata a questi.

C'è anche un'opzione possibile da questa domanda sullo overflow dello stack , ma non ho ancora avuto la possibilità di implementarla; e un'altra possibilità qui .


1
Grazie per aver pubblicato gli esempi. Questo post su CV mostra un codice più bello per i grafici di ParSet in R (scusatemi avrei dovuto puntarlo prima). La mia incursione nel pacchetto ggparallel suggerisce che finora è piuttosto approssimativo (anche se i dati casuali come te mostrano non tenderanno a sembrare belli IMO per ParSet).
Andy W,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.