可视化来自多个潜在类模型的结果


9

我正在使用潜在类分析来基于一组二进制变量对观察样本进行聚类。我正在使用R和软件包poLCA。在LCA中,您必须指定要查找的群集数。实际上,人们通常运行几个模型,每个模型指定不同数量的类,然后使用各种标准来确定哪个是对数据的“最佳”解释。

我经常发现查看各种模型非常有用,以试图了解分类为(i + 1)的模型如何分布在分类为(i)的模型中的观察结果。至少,有时您会发现存在非常健壮的集群,而与模型中的类数无关。

我希望有一种方法来绘制这些关系的图表,以便更轻松地在论文中以及与非统计方向的同事交流这些复杂的结果。我想使用某种简单的网络图形包在R中很容易做到这一点,但我根本不知道如何做。

谁能给我指出正确的方向。下面是重现示例数据集的代码。每个向量xi在具有i个可能类别的模型中代表100个观测值的分类。我想画出观察(行)如何跨列在类之间移动。

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)

我想有一种方法可以生成图,其中节点是分类,并且边缘反映(按权重或颜色)(从权重或颜色可能)从一个模型转移到另一个模型的观察值的百分比。例如

在此处输入图片说明

更新:igraph软件包取得了一些进展。从上面的代码开始...

poLCA结果循环使用相同的数字来描述类成员身份,因此您需要做一些重新编码。

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

然后,您需要获取所有交叉表及其频率,并将它们重新绑定到一个定义所有边缘的矩阵中。可能有一种更为优雅的方法来执行此操作。

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)

在此处输入图片说明

我猜是时候该玩igraph选项了。


1
如果您找到了满意的解决方案,也可以将代码发布为答案
晚宴

2
这正在变成像parsets之类的东西。有关R的实现,请参见ggparallel
安迪W

1
直到我注意到@Andy的评论之前,我一直在思考类似簇图(带有受试者ID而不是簇的编号)或流图(如果簇少的话,吸引力可能会降低)。当然,这假设您愿意在个人层面上工作。
chl

Answers:


3

到目前为止,由于您的建议,我发现的最佳选择是:

  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)

用igraph做

随着Igraph

用ggparallel完成

与ggparallel

仍然很难在期刊上分享,但是我当然发现快速浏览这些内容非常有用。

这个问题在堆栈溢出时也有可能的选择,但是我还没有实现它的机会。而另一种可能在这里


1
感谢您发布示例。CV上的这篇文章显示了R中ParSets绘图的一些更好的代码(对不起,应该先指出这一点)。我对ggparallel软件包的尝试表明,到目前为止,它在边缘上还是很粗糙的(尽管像您所示的随机数据在ParSets上看起来不太适合IMO)。
安迪W
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.