创建关于r

时间:2018-11-26 22:51:35

标签: r plot parallel-coordinates

我有如下DF。它包含有关两个学生三个学期的信息,以及他们是否合格。
我想绘制一个平行坐标。我想看看走到底的路。

ID  term  subject  result
1    1     math01    fail
1    1     Phys01    pass
1    1     chem01    pass
1    2     math01    pass
1    2     math02    fail
1    3     math02    fail
1    3     cmp01     pass
2    1     math01    fail
2    1     phys01    pass
2    2     math01    pass
2    2     math02    pass
2    3     cmp01     pass

所需的结果类似于下图。
 每个学期的每个方框都显示带有result列(失败或通过)的科目别名。块的大小应对应于所拍摄主题的数量。例如,如果大多数学生在第1学期未通过math01,则math01fail的块应该是在term1以下的最大块。

连接线将学生在学期中选修的科目与下一学期联系起来。线的粗细对应于该点的连接数。例如,如果许多学生在term1上不通过math01(math01fail),而在term2上重新通过math01并通过(math01pass),则考虑到出现的次数,math01fail与math01pass之间的连接线应该更粗。

如何在R中创建这样的图? enter image description here

1 个答案:

答案 0 :(得分:1)

我认为您最好从图形的角度解决此问题,而不是在平行坐标的情况下。

这就是我要做的:

  1. 从加载必要的库开始

    library(tidyverse)
    library(igraph)
    
  2. 首先,我们定义图的边缘列表。为此,我们用df进行ID的自联接,并选择与连续(递增)项相对应的行。然后,每一行对应于每个学生从学期i到i + 1的链接。

    el <- left_join(df, df, by = "ID") %>%
        filter(term.x == term.y - 1) %>%
        mutate_at(vars(starts_with("term")), funs(paste0("term", .))) %>%
        unite(from, term.x, subject.x, result.x, sep = "\n") %>%
        unite(to, term.y, subject.y, result.y, sep = "\n") %>%
        select(from, to) %>%
        group_by(from, to) %>%
        summarise(weight = (n() - 1) * 5 + 1)
    

    我们添加了一个权重列,该列与每个边缘的学生数量成正比。我们之所以不简单地weight = n(),原因纯粹是出于美学考虑,我们喜欢为1个以上的学生提供较粗的线条。

  3. 接下来,我们定义一个节点列表。此处的关键是添加xy列,这些列将确定节点的网格布局。

    nl <- df %>%
        mutate(term = paste0("term", term)) %>%
        arrange(term) %>%
        distinct(term, subject, result) %>%
        mutate(x = as.integer(as.factor(term))) %>%
        group_by(term) %>%
        mutate(y = 1:n()) %>%
        unite(node, term, subject, result, sep = "\n")
    

    请注意,nl第一栏中的条目必须与el前两栏中的条目相匹配。

  4. 我们现在准备从两个igraph构造一个data.frame并绘制图形。

    gr <- graph_from_data_frame(d = el, vertices = nl, directed = F)
    plot(
        gr,
        edge.width = E(gr)$weight,
        vertex.shape = "rectangle",
        vertex.size = 50, vertex.size2 = 50,
        vertex.color = "white",
        vertex.label.family = "sans",
        vertex.label.cex = 0.7)
    

    enter image description here

    生成的图可能需要进一步调整/抛光,但这应该可以帮助您入门。