【问题标题】:Data preparation for Sankey Data in R to get flow frequency在 R 中为 Sankey Data 准备数据以获得流动频率
【发布时间】:2017-12-14 08:47:57
【问题描述】:

我尝试使用 ggalluvial 和 networkd3 软件包创建一个桑基图,但未能成功。理想情况下,我想了解如何在两者中获得我想要做的事情。

数据生成如下:

dat <- data.frame(customer = c(rep(c(1, 2), each=3), 3, 3),
              holiday_loc = c("SA", "SA", "AB", "SA", "SA", "SA", "AB", "AB"),
              holiday_num = c(1, 2, 3, 1, 2, 3, 1, 2))

dat_wide <- dat %>%
        spread(key=holiday_num, value=holiday_loc`)

不确定 dat 还是 dat_wide 更合适? 我希望输出可视化以下信息(括号中的数字是频率,因此是流的宽度)

SA -(2) - SA - (1) - AB

           - (1) - SA

AB -(1) - AB

我按照此链接上关于 networkd3 Sankey diagram for Discrete State Sequences in R using networkd3 的说明进行操作,但最终在图中出现了循环。

下图显示了我想要的类似图表: [![桑基图取自 SAS VA][2]][2]

我们将不胜感激您的建议和帮助...

谢谢!

[2]:https://i.stack.imgur.com/wTJ1k.png

【问题讨论】:

  • 我不了解您的(样本)数据。桑基图是有向(加权)图的可视化。您的(加权)链接(边)和节点(顶点)集在哪里?

标签: r sankey-diagram networkd3


【解决方案1】:

您的数据的核心问题(在networkD3 术语中)是您有同名的节点,因此您需要区分它们,至少在处理数据时是这样。

结合位置和数量信息来制作可区分的节点,然后将你的数据转换成一个链接数据框,像这样......

links <- 
  dat %>% 
  mutate("source" = paste(holiday_loc, holiday_num, sep = "_")) %>% 
  group_by(customer) %>% 
  arrange(holiday_num) %>% 
  mutate("target" =  lead(source)) %>% 
  ungroup() %>% 
  arrange(customer) %>% 
  filter(!is.na(target)) %>% 
  select(source, target)

由此,您可以构建一个节点数据框,其中包含每个不同节点的一行,如下所示...

node_names <- factor(sort(unique(c(as.character(links$source), 
                                   as.character(links$target)))))
nodes <- data.frame(name = node_names)

然后将链接数据帧转换为使用节点数据帧中节点的索引(0-indexed,因为它最终会传递给 JavaScript),像这样......

links <- data.frame(source = match(links$source, node_names) - 1, 
                    target = match(links$target, node_names) - 1,
                    value = 1)

此时,如果您希望节点具有不明确的名称,您现在可以更改它,如下所示...

nodes$name <- sub("_[0-9]$", "", nodes$name)

现在你可以绘制它了...

library(networkD3)
sankeyNetwork(links, nodes, "source", "target", "value", "name")

【讨论】:

  • 有没有办法指定流是左对齐而不是右对齐?即顶部流 wld 从索引 0 开始。否则,我将使用一个解决方法,即使用虚拟节点进行“drop off”并重命名为空白字符,这样可以正常工作。
  • 查看帮助文件...sinksRight = F
【解决方案2】:

我发现冲积包对这项任务很有用,但我不知道这是否是您锁定的目的:

library(tidyverse)
library(alluvial)
dat <- data.frame(customer = c(rep(c(1, 2), each=3), 3, 3),
                  holiday_loc = c("SA", "SA", "AB", "SA", "SA", "SA", "AB", "AB"),
                  holiday_num = c(1, 2, 3, 1, 2, 3, 1, 2))

dat_summarized <- dat %>% group_by(holiday_num, holiday_loc, customer) %>%
  summarise(n = n()) %>% mutate(color = recode(customer,
                                               `1` = "cadetblue1",
                                               `2` = "cadetblue2",
                                               `3` = "cadetblue3"))

alluvial(dat_summarized[1:3],
         freq = dat_summarized$n,
         col = dat_summarized$color)

【讨论】:

  • 我刚刚添加了一张照片,希望它更清晰。我不希望每个客户一行,而是要链接显示从假日编号 i 的位置 x 到假日编号 i + 1 的位置 y 的客户数量。
猜你喜欢
  • 2016-02-03
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 2022-11-18
相关资源
最近更新 更多