您需要两个数据框:一个列出所有节点(包含名称),一个列出链接。后者包含三列,源节点、目标节点和一些值,表示链接的强度或宽度。在链接数据框中,您通过节点数据框中的(从零开始的)位置来引用节点。
假设您的数据如下所示:
df <- data.frame(Year1=sample(paste0("Hotel", 1:4), 1000, replace = TRUE),
Year2=sample(paste0("Hotel", 1:4), 1000, replace = TRUE),
Year3=sample(paste0("Hotel", 1:4), 1000, replace = TRUE),
Year4=sample(paste0("Hotel", 1:4), 1000, replace = TRUE),
stringsAsFactors = FALSE)
对于图表,您不仅需要区分酒店,还需要区分酒店/年份组合,因为它们中的每一个都应该是一个节点:
df$Year1 <- paste0("Year1_", df$Year1)
df$Year2 <- paste0("Year2_", df$Year2)
df$Year3 <- paste0("Year3_", df$Year3)
df$Year4 <- paste0("Year4_", df$Year4)
链接是酒店之间从一年到下一年的“过渡”:
library(dplyr)
trans1_2 <- df %>% group_by(Year1, Year2) %>% summarise(sum=n())
trans2_3 <- df %>% group_by(Year2, Year3) %>% summarise(sum=n())
trans3_4 <- df %>% group_by(Year3, Year4) %>% summarise(sum=n())
colnames(trans1_2)[1:2] <- colnames(trans2_3)[1:2] <- colnames(trans3_4)[1:2] <- c("source","target")
links <- rbind(as.data.frame(trans1_2),
as.data.frame(trans2_3),
as.data.frame(trans3_4))
最后,数据框需要相互引用:
nodes <- data.frame(name=unique(c(links$source, links$target)))
links$source <- match(links$source, nodes$name) - 1
links$target <- match(links$target, nodes$name) - 1
然后就可以画图了:
library(networkD3)
sankeyNetwork(Links = links, Nodes = nodes, Source = "source",
Target = "target", Value = "sum", NodeID = "name",
fontSize = 12, nodeWidth = 30)
可能有更优雅的解决方案,但这可能是您的问题的起点。如果您不喜欢节点名称中的“年份...”,您可以在设置数据框后将其删除。