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

机器算法验证 数据可视化 混合分布 潜类
2022-03-08 05:26:29

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

我经常发现查看各种模型非常有用,以尝试了解在 class=(i) 的模型中分类的观察结果如何由 class = (i+1) 的模型分布。至少,您有时可以找到非常健壮的集群,无论模型中的类数量如何。

我想要一种方法来绘制这些关系,以便更轻松地将这些复杂的结果在论文中传达给不以统计为导向的同事。我想这在 R 中使用某种简单的网络图形包很容易做到,但我根本不知道怎么做。

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

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个回答

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

  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

仍然太粗糙,无法在日记中分享,但我确实发现快速浏览这些非常有用。

这个问题还有一个关于堆栈溢出的可能选项,但我还没有机会实现它;还有另一种可能