【问题标题】:How to prepare input data for a sankey diagrams in R?如何为 R 中的 sankey 图准备输入数据?
【发布时间】:2016-02-03 15:02:15
【问题描述】:

我正在尝试在 R 中生成 sankey diagram,这也称为河图。我已经看到了这个问题Sankey Diagrams in R?,其中列出了各种各样的生成 sankey 图的包。因为我有输入数据并且知道不同的工具/包,所以我可以制作这样的图表,但我的问题是:我怎样才能为此准备输入数据?

假设我们想展示用户在 10 天内如何在不同状态之间迁移,并拥有如下所示的起始数据集:

data.frame(userID = 1:100,
                     day1_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day2_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day3_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day4_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day5_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day6_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day7_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day8_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day9_state = sample(letters[1:8], replace = TRUE, size = 100),
                     day10_state = sample(letters[1:8], replace = TRUE, size = 100)
                     ) -> dt

现在,如果想用networkD3 package 创建一个桑基图,应该如何将这个dt data.frame 转换为所需的输入

这样我们就可以从这个例子中获得输入

library(networkD3)
URL <- paste0(
        "https://cdn.rawgit.com/christophergandrud/networkD3/",
        "master/JSONdata/energy.json")
Energy <- jsonlite::fromJSON(URL)
# Plot
sankeyNetwork(Links = Energy$links, Nodes = Energy$nodes, Source = "source",
             Target = "target", Value = "value", NodeID = "name",
             units = "TWh", fontSize = 12, nodeWidth = 30)

编辑

我发现这样的脚本可以在其他情况下准备数据并复制它,所以我认为它现在可能会关闭:

https://github.com/mi2-warsaw/JakOniGlosowali/blob/master/sankey/sankey.R

【问题讨论】:

  • 您也可以考虑为您的问题提供答案,而不是关闭它。这可能对其他人有帮助
  • 好的,我已经上传了一个带有示例和答案的代码:)

标签: r data-visualization sankey-diagram networkd3


【解决方案1】:

I asked a similar question while ago. 我想我最好在这里发布它如何使用tidyverse 魔法来完成。

library(ggplot2)
library(ggalluvial)
library(tidyr)
library(dplyr)
library(stringr)

# The actual data preperation happens here
dt_new  <- dt  %>% 
gather(day, state, -userID)  %>% # Long format
mutate(day = str_match(day, "[0-9]+")[,1])  %>% # Get the numbers 
  mutate(day = as.integer(day), # Convert to proper data types
         state = as.factor(state))

这是数据dt_new 的样子

   userID day state
1       1   1     d
2       2   1     d
3       3   1     g
4       4   1     a
5       5   1     a
6       6   1     d
7       7   1     d
8       8   1     b
9       9   1     d
10     10   1     e
...

现在绘制桑基图:

  ggplot(dt_new,
       aes(x = day, stratum = state, alluvium = userID, fill = state, label = state)) +
  geom_stratum() +
  geom_text(stat = "stratum") +
  geom_flow()

这是输出

【讨论】:

    【解决方案2】:

    我发现这样的脚本可以在其他情况下准备数据并复制它,所以我认为它现在可能会关闭:

    https://github.com/mi2-warsaw/JakOniGlosowali/blob/master/sankey/sankey.R

    然后这段代码为问题data.frame中提到的生成这样的sankey图

    fixtable <- function(...) {
        tab <- table(...)
        if (substr(colnames(tab)[1],1,1) == "_" &
                    substr(rownames(tab)[1],1,1) == "_") {
            tab2 <- tab
            colnames(tab2) <- sapply(strsplit(colnames(tab2), split=" "), `[`, 1)
            rownames(tab2) <- sapply(strsplit(rownames(tab2), split=" "), `[`, 1)
            tab2[1,1] <- 0
            # mandat w klubie
            for (par in names(which(tab2[1,] > 0))) {
                delta = min(tab2[par, 1], tab2[1, par])
                tab2[par, par] = tab2[par, par] + delta
                tab2[1, par] = tab2[1, par] - delta
                tab2[par, 1] = tab2[par, 1] - delta
            }
            # przechodzi przez niezalezy
            for (par in names(which(tab2[1,] > 0))) {
                tab2["niez.", par] = tab2["niez.", par] + tab2[1, par]
                tab2[1, par] = 0
            }
            for (par in names(which(tab2[,1] > 0))) {
                tab2[par, "niez."] = tab2[par, "niez."] + tab2[par, 1]
                tab2[par, 1] = 0
            }
    
            tab[] <- tab2[] 
        }
        tab
    }
    
    
    flow2 <- rbind(
        data.frame(fixtable(z = paste0(dat$day1_state, " day1"), do = paste0(dat$day2_state, " day2"))),
        data.frame(fixtable(z = paste0(dat$day2_state, " day2"), do = paste0(dat$day3_state, " day3"))),
        data.frame(fixtable(z = paste0(dat$day3_state, " day3"), do = paste0(dat$day4_state, " day4"))),
        data.frame(fixtable(z = paste0(dat$day4_state, " day4"), do = paste0(dat$day5_state, " day5"))),
        data.frame(fixtable(z = paste0(dat$day5_state, " day5"), do = paste0(dat$day6_state, " day6"))),
        data.frame(fixtable(z = paste0(dat$day6_state, " day6"), do = paste0(dat$day7_state, " day7"))),
        data.frame(fixtable(z = paste0(dat$day7_state, " day7"), do = paste0(dat$day8_state, " day8"))),
        data.frame(fixtable(z = paste0(dat$day8_state, " day8"), do = paste0(dat$day9_state, " day9"))),
        data.frame(fixtable(z = paste0(dat$day9_state, " day9"), do = paste0(dat$day10_state, " day10"))))
    
    flow2 <- flow2[flow2[,3] > 0,]
    
    nodes2 <- data.frame(name=unique(c(levels(factor(flow2[,1])), levels(factor(flow2[,2])))))
    nam2 <- seq_along(nodes2[,1])-1
    names(nam2) <- nodes2[,1]
    
    links2 <- data.frame(source = nam2[as.character(flow2[,1])],
                                            target = nam2[as.character(flow2[,2])],
                                            value = flow2[,3])
    
    sankeyNetwork(Links = links, Nodes = nodes,
                                Source = "source", Target = "target",
                                Value = "value", NodeID = "name",
                                fontFamily = "Arial", fontSize = 12, nodeWidth = 40,
                                colourScale = "d3.scale.category20()")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2016-07-05
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多