如果源节点和目标节点具有相同的名称,如何使用 networkD3 创建桑基图

How to create a sankey diagram with networkD3 if source and target nodes have the same names

我正在尝试使用 package in 构建桑基图。

我想我已经以正确的方式设置了数据集,从 table 开始。这是我的代码:

M <- data.frame(as.matrix( table(as.character(df$q4.1),as.character(df$q4.2))))

M <- filter(M, Freq !=0)

q4.1 和 q4.2 是两个类别相同的分类变量。我对可视化从 q4.1 到 q4.2 中的答案的流程很感兴趣。

nodes <- data.frame(
  name=c(as.character(M$Var1), as.character(M$Var2)) %>% unique()
)

问题是,鉴于这两个变量具有相同的名称,当我创建节点时,它只包含一组 "names"。

因此,如果有人在两个问题中都选择了相同的选项,那么它最终会具有相同的源和目标(参见下面的示例)

M$IDsource <- match(M$Var1, nodes$name)-1 

M$IDtarget <- match(M$Var2, nodes$name)-1

M

Var1             Var2 Freq IDsource IDtarget

No idea      No idea   16        7        7

如您所想,结果图很奇怪,因为对两个问题提供相同答案的人显示为返回同一来源的圆圈。

是否只有重命名第二个问题中的类别才能解决问题?或者我做错了什么?

感谢支持!

P.S。我已经在 ggplot2 中使用了 ggalluvial 包来创建我想要的图形。但是,它不像使用 networkD3 包获得的图那么好(并且 exportable 作为 htmlwidget),所以我想用 networkD3 重新创建相同的图。 这是我与 ggalluvial 包一起使用的成功代码。

ggplot(data= M, aes(axis1= Var1, axis2= Var2, y= Freq)) + scale_x_discrete(limits = c("Next 6 months", "Next 12-18 Months"), expand=c(0.1, 0.05)) + geom_alluvium() + geom_stratum() + geom_text(stat="stratum", infer.label = TRUE)

networkD3::sankeyNetwork中,节点数据框的索引(行号)是链接和节点数据框之间的键,而不是'name'。因此,您可以在节点数据框中有多个相同的名称,但如果它们是为了标识不同的节点,则它们必须位于不同的行上。

例如,假设您的数据看起来像这样...

library(networkD3)
library(dplyr)

M <- expand.grid(Var1 = LETTERS[1:4], 
                 Var2 = LETTERS[1:4], 
                 stringsAsFactors = F)

M$Freq <- sample(1:100, nrow(M))

M
#>    Var1 Var2 Freq
#> 1     A    A   81
#> 2     B    A   84
#> 3     C    A   42
#> 4     D    A   71
#> 5     A    B    9
#> 6     B    B   79
#> 7     C    B   82
#> 8     D    B   76
#> 9     A    C   41
#> 10    B    C   63
#> 11    C    C   95
#> 12    D    C   61
#> 13    A    D   33
#> 14    B    D    2
#> 15    C    D   13
#> 16    D    D   38

为值添加一些标识符,以便您可以区分它们来自哪个问题,例如...

M$Var1 <- paste0(M$Var1, '_q41')
M$Var2 <- paste0(M$Var2, '_q42')

M
#>     Var1  Var2 Freq
#> 1  A_q41 A_q42    9
#> 2  B_q41 A_q42   86
#> 3  C_q41 A_q42   62
#> 4  D_q41 A_q42   26
#> 5  A_q41 B_q42   44
#> 6  B_q41 B_q42   93
#> 7  C_q41 B_q42   36
#> 8  D_q41 B_q42   51
#> 9  A_q41 C_q42    6
#> 10 B_q41 C_q42    5
#> 11 C_q41 C_q42   21
#> 12 D_q41 C_q42   83
#> 13 A_q41 D_q42   40
#> 14 B_q41 D_q42   77
#> 15 C_q41 D_q42   20
#> 16 D_q41 D_q42   85

做同样的事情来获取节点的唯一列表,然后将链接数据框与它们匹配...

nodes <- data.frame(
  name=c(as.character(M$Var1), as.character(M$Var2)) %>% unique()
)

M$IDsource <- match(M$Var1, nodes$name)-1

M$IDtarget <- match(M$Var2, nodes$name)-1

nodes
#>    name
#> 1 A_q41
#> 2 B_q41
#> 3 C_q41
#> 4 D_q41
#> 5 A_q42
#> 6 B_q42
#> 7 C_q42
#> 8 D_q42

M
#>     Var1  Var2 Freq IDsource IDtarget
#> 1  A_q41 A_q42    9        0        4
#> 2  B_q41 A_q42   86        1        4
#> 3  C_q41 A_q42   62        2        4
#> 4  D_q41 A_q42   26        3        4
#> 5  A_q41 B_q42   44        0        5
#> 6  B_q41 B_q42   93        1        5
#> 7  C_q41 B_q42   36        2        5
#> 8  D_q41 B_q42   51        3        5
#> 9  A_q41 C_q42    6        0        6
#> 10 B_q41 C_q42    5        1        6
#> 11 C_q41 C_q42   21        2        6
#> 12 D_q41 C_q42   83        3        6
#> 13 A_q41 D_q42   40        0        7
#> 14 B_q41 D_q42   77        1        7
#> 15 C_q41 D_q42   20        2        7
#> 16 D_q41 D_q42   85        3        7

如果您不希望问题后缀在 Sankey 输出中可见,您可以在您已经匹配正确索引后立即将其删除...

nodes$name <- sub('_q4[1-2]$', '', nodes$name)

然后打印...

sankeyNetwork(M, nodes, 'IDsource', 'IDtarget', 'Freq', 'name')