代码之家  ›  专栏  ›  技术社区  ›  user1420372

R中Sankey数据的数据准备,以获取流量频率

  •  4
  • user1420372  · 技术社区  · 7 年前

    我曾尝试使用GG冲积和networkd3包创建一个Sankey图,但至今未能成功。理想情况下,我想了解如何在这两个方面都得到我想要的东西。

    数据生成如下:

    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\U wide是否更合适? 我希望输出能够可视化以下信息(括号中的数字是频率,因此是流的宽度)

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

               - (1) - SA
    

    AB-(1)-AB

    我遵循了networkd3链接上的说明 Sankey diagram for Discrete State Sequences in R using networkd3 然而,我最终在图中找到了循环。

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

    非常感谢您的建议和帮助。。。

    谢谢

    [2]: https://i.stack.imgur.com/wTJ1k.png enter image description here

    2 回复  |  直到 7 年前
        1
  •  5
  •   CJ Yetman    7 年前

    数据的核心问题(在 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-index,因为它最终会传递给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")
    

    sankey plot

        2
  •  0
  •   AaronP    7 年前

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

    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)
    

    alluvial