r - 如果源节点和目标节点具有相同的名称,如何使用 networkD3 创建 sankey 图
问题描述
我想我已经以正确的方式设置了数据集,从表格开始。这是我的代码:
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()
)
问题是,鉴于这两个变量具有相同的名称,当我创建节点时,它只包含一组“名称”。
因此,如果有人在两个问题中选择了相同的选项,它最终会具有相同的源和目标(请参见下面的示例)
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
可以想象,结果图很奇怪,因为对两个问题提供相同答案的人显示为返回同一来源的圆圈。
重命名第二个问题中的类别是解决问题的唯一可能性吗?或者我做错了什么?
感谢您的支持!
PS 我已经在 ggplot2 中使用了 ggalluvial 包来创建我想要的图形。但是,它不如使用 networkD3 包获得的图那么好(并且可以导出为 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
中,节点数据框的索引(行号)是链接和节点数据框之间的键,而不是“名称”。因此,您可以在节点数据框中有多个相同的名称,但如果它们旨在识别不同的节点,它们必须位于不同的行上。
例如,假设您有看起来像这样的数据......
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')
推荐阅读
- elasticsearch - ElasticSearch多词查询,匹配多词比匹配少而多更有价值
- virtual-reality - godot vr 中的 find_interface: error 是什么意思?
- r - 文档对象中的非文件包锚定链接
- mongodb - MongoDB GridFS 巨大的 wt 文件
- reactjs - 反应钩子。如何使输入显示并在 setstate 值后获得输入的焦点?谢谢
- wxpython - 如何使用 wxpython 开发应用程序?
- token - 尝试使用 url 时,https://vrp.api.here.com/v1/problems,api 返回错误 403
- python - python:为XML树中的当前节点生成xPath选择器
- r - R,tidyverse:如何将 spread() 与 group_by() 一起使用
- javascript - jquery将每个单词的第一个字母大写