【问题标题】:How does sankeyNetwork set x axis positionsankeyNetwork如何设置x轴位置
【发布时间】:2021-12-08 16:31:57
【问题描述】:

我正在通过networkD3::sankeyNetwork() 中使用 构建一个sankey plot 的文档和教程。

我可以使用其他人的代码来完成这项工作(来自这里:sankey diagram in R - data preparation - 请参阅 CJ Yetman 的 networkd3 的 tidyverse 方式)

当我自己尝试实现这一点时,我的节点在 x 轴上的排列顺序错误 - 导致流程无法理解。

但是我无法确定sankeyNetwork 在哪里获取有关 x 轴位置的信息。

这是我的实现,但没有产生预期的结果:

library(tidyverse)
library(networkD3)

#Create the data
df <- data.frame('one' = c('a', 'b', 'b', 'a'), 
                 'two' = c('c', 'd', 'e', 'c'), 
                 'three' = c('f', 'g', 'f', 'f'))

#My code
#Create the links
links <- df %>%
  mutate(row = row_number()) %>% #Get row for grouping and pivoting
  pivot_longer(-row) %>% #pivot to long format
  group_by(row) %>% 
  mutate(source_c = lead(value)) %>% #Get flow 
  filter(!is.na(source_c)) %>% #Get rid of NA
  rename(target_c = value) %>% #Correct names
  group_by(target_c, source_c) %>% #Count frequencies
  summarize(value = n()) %>%
  ungroup() %>%
  mutate(target = as.integer(factor(target_c)), #Convert to numeric values
         source = as.integer(factor(source_c))) %>%
  mutate(source = source - 1, #zero index
         target = target - 1) %>%
  data.frame()

#create the nodes
nodes <- data.frame(name = factor(unique(c(links$target_c, links$source_c))))

#plot the network
sankeyNetwork(Links = links, Nodes = nodes, Source = 'source',
              Target = 'target', Value = 'value', NodeID = 'name')

产量:

使用链接答案中的工作代码:

links <-
  df %>% 
  mutate(row = row_number()) %>%  # add a row id
  gather('col', 'source', -row) %>%  # gather all columns
  mutate(col = match(col, names(df))) %>%  # convert col names to col nums
  mutate(source = paste0(source, '_', col)) %>%  # add col num to node names
  group_by(row) %>%
  arrange(col) %>%
  mutate(target = lead(source)) %>%  # get target from following node in row
  ungroup() %>% 
  filter(!is.na(target)) %>%  # remove links from last column in original data
  select(source, target) %>% 
  group_by(source, target) %>% 
  summarise(value = n())  # aggregate and count similar links

# create nodes data frame from unque nodes found in links data frame
nodes <- data.frame(id = unique(c(links$source, links$target)),
                    stringsAsFactors = FALSE)
# remove column id from names
nodes$name <- sub('_[0-9]*$', '', nodes$id)

# set links data to the 0-based index of the nodes in the nodes data frame
links$source <- match(links$source, nodes$id) - 1
links$target <- match(links$target, nodes$id) - 1

sankeyNetwork(Links = links, Nodes = nodes, Source = 'source',
              Target = 'target', Value = 'value', NodeID = 'name')

产生一个工作结果:

我很欣赏工作代码和我的代码不同,但我看不到 sankeyNetwork 调用行号(即 x 轴)数据的位置 - 没有调用包含该信息的任何变量.我想我可以让我自己的代码工作来准备数据,一旦我知道它需要是什么样子。

【问题讨论】:

    标签: networkd3 r javascript r d3.js htmlwidgets networkd3


    【解决方案1】:

    中的所有函数一样,sankeyNetwork() 根据它们与网络中其他节点的关系通过算法确定节点的xy 位置,它不会读取x 和@ 987654328@ 值直接来自数据。

    您的代码版本与您复制的代码不同的原因是您如何分解然后强制将链接数据框中的目标和源节点名称分别进行整数化。这样一来,您与源列或目标列中给定节点关联的值就会不同步,因此您的链接与开始时的链接完全不同。

    查看您的 links 数据框并与您开始使用的 df 数据框进行比较。例如,links 数据框中的第一行/链接是a-&gt;c,但您的targetsource 列将其标识为0-&gt;0。同样,第二行/链接是b-&gt;d,但您的targetsource 列将其标识为1-&gt;1。等等……

    links
    #   target_c source_c value target source
    # 1        a        c     2      0      0
    # 2        b        d     1      1      1
    # 3        b        e     1      1      2
    # 4        c        f     2      2      3
    # 5        d        g     1      3      4
    # 6        e        f     1      4      3
    

    此外,由于您在复制的其他代码中使用 mutate(source_c = lead(value)) 而不是 mutate(target = lead(source)),因此您反转了链接流,因此您将获得预期的镜像。

    如果您必须在 dplyr 链内的链接数据框中设置目标和源节点 ID 并像这样改变命令,您可以将 factor 命令的级别设置为相同的东西,结合两列中的所有唯一值,喜欢(但您仍然必须颠倒源与目标的概念才能获得与复制代码相同的结果)...

    library(tidyverse)
    library(networkD3)
    
    #Create the data
    df <- data.frame('one' = c('a', 'b', 'b', 'a'), 
                     'two' = c('c', 'd', 'e', 'c'), 
                     'three' = c('f', 'g', 'f', 'f'))
    
    #My code
    #Create the links
    links <- 
      df %>%
      mutate(row = row_number()) %>% #Get row for grouping and pivoting
      pivot_longer(-row) %>% #pivot to long format
      group_by(row) %>% 
      mutate(source_c = lead(value)) %>% #Get flow 
      filter(!is.na(source_c)) %>% #Get rid of NA
      rename(target_c = value) %>% #Correct names
      group_by(target_c, source_c) %>% #Count frequencies
      summarize(value = n()) %>%
      ungroup() %>%
      mutate(target = as.integer(factor(target_c, level = unique(c(target_c, source_c)))), #Convert to numeric values
             source = as.integer(factor(source_c, level = unique(c(target_c, source_c))))) %>%
      mutate(source = source - 1, #zero index
             target = target - 1) %>%
      data.frame()
    
    #create the nodes
    nodes <- data.frame(name = factor(unique(c(links$target_c, links$source_c))))
    
    #plot the network
    sankeyNetwork(Links = links, Nodes = nodes, Source = 'source',
                  Target = 'target', Value = 'value', NodeID = 'name')
    

    【讨论】:

    • 非常感谢您花时间向我解释这一点。
    猜你喜欢
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多