R中的Sankey图?


86

我正在尝试使用R中的Sankey Diagram可视化我的数据流。

我发现此博客文章链接到生成Sankey Diagram的R脚本,不幸的是,它是原始的并且有所限制(请参见下面的示例代码和数据)。

有谁知道其他脚本或什至是软件包吗?我的最终目标是通过图表组件的相对大小来可视化数据流和百分比,就像这些Sankey Diagrams示例一样。

在r-help列表上发布了一个类似的问题,但是两周后没有任何回应,我在这里尝试了我的运气。

谢谢,埃里克

PS。我知道Parallel Sets Plot,但这不是我想要的。

# thanks to, https://tonybreyal.wordpress.com/2011/11/24/source_https-sourcing-an-r-script-from-github/
  sourc.https     <- function(url, ...) {
# install and load the RCurl package 
if (match('RCurl', nomatch=0, installed.packages()[,1])==0) {
  install.packages(c("RCurl"), dependencies = TRUE)
  require(RCurl)  
} else require(RCurl)    

# parse and evaluate each .R script
  sapply(c(url, ...), function(u) {
    eval(parse(text = getURL(u, followlocation = TRUE, 
    cainfo  = system.file("CurlSSL", "cacert.pem", 
    package = "RCurl"))), envir = .GlobalEnv)
 } )
 }

# from https://gist.github.com/1423501
sourc.https("https://raw.github.com/gist/1423501/55b3c6f11e4918cb6264492528b1ad01c429e581/Sankey.R")

# My example (there is another example inside Sankey.R):
inputs = c(6, 144)
losses = c(6,47,14,7, 7, 35, 34)
unit = "n ="

labels = c("Transfers",
           "Referrals\n",
           "Unable to Engage",
           "Consultation only",
           "Did not complete the intake",
           "Did not engage in Treatment",
           "Discontinued Mid-Treatment",
           "Completed Treatment",
           "Active in \nTreatment")

SankeyR(inputs,losses,unit,labels)

# Clean up my mess
rm("inputs", "labels", "losses", "SankeyR", "sourc.https", "unit")

用以上代码生成的Sankey图, 用上面的代码生成的Sankey图


2
箭头对我来说看起来不错,看起来您需要微调文本,并且您进入其中?
RomanLuštrik2012年

@RomanLuštrik,我同意,这张图一点也不差,但是我的R技能仍然很有限,所以我真的不能在R中做那么多的微调,如果那是你的意思呢?我当然可以在Adobe Illustrator或类似工具中做到这一点,但这会破坏可重复研究的原理,对我而言,这是任何(学术)作品的核心要素。您是否看过我在帖子中链接的示例
Eric Fail

我意识到我的问题不是一个很好的问题,因为它不是一个特定的编程问题,也不是直接实用的,而是一个开放性的问题(来自FAQ)。要回答这个问题,要么要么必须对R中的不同图形选项进行监督,然后在此基础上回答“否”,就不存在更成熟的笔迹或软件包,或者需要知道一个更先进的方法来在R中生成Sankey图并指向它。也许有更好的地方发布这个问题?
Eric Fail 2012年

1
我唯一能想到的地方可能是crossvalidated.com。
RomanLuštrik'12

R-help邮件列表如何?r-project.org/mail.html
亚历克斯·雷诺兹

Answers:


63

可以通过networkD3包创建该图。它允许您创建交互式sankey图。在这里您可以找到一个例子。我还添加了一个屏幕截图,以便您了解它的外观。

# Load package
library(networkD3)

# Load energy projection data
# Load energy projection data
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)

在此处输入图片说明


4
示例链接已损坏
rmstmppr

1
确实。由于引入了一个更好的选择,那htmlwidgets就是networkD3包装中的sankey图。我更新了帖子。
乔纳斯·汤多

1
是否可以将数字值作为标题而不是整数?正确地使用了值,但标题似乎已四舍五入。例如:value = 0.8和value = 0.2具有不同的线宽,但标题中的两个都为“ 0”。
Naveen Mathew

如果您尝试使用自己的数据样本重现此信息,请确保第一个源ID以0开头,并且源ID和目标ID是连续的
Richard

43

我创建了一个包(riverplot),该包与Sankey函数相比具有稍微不同但重叠的功能,并且可以生成如下图:

在此处输入图片说明


这看起来确实令人印象深刻!我将尽快查看。
Eric Fail 2014年

39

如果您想使用R进行操作,则最好的出价似乎是@Roman建议-修改SankeyR函数。例如,下面是我的快速解决方法,只需将标签垂直放置,适当地偏移它们,并减小输入参照的字体,以使其看起来更好。此修改仅更改SankeyR函数中的行171和223 :

    #line171 - change oversized font size of input label
    fontsize = max(0.5,frInputs[j]*1.5)#1.5 instead of 2.5 

    #line223 - srt changes from 35 to 90 to orient labels vertically, 
    #and offset adjusts them to get better alignment with arrows
    text(txtX, txtY, fullLabel, cex=fontsize, pos=4, srt=90, offset=0.1)

在此处输入图片说明

我不是三角学的王牌,但这确实是改变箭头方向所需要的。在我看来,这是理想的选择-如果您可以调整松动箭头,使它们水平而不是垂直。否则,为什么我的解决方案解决了标签方向问题,但并没有使图表更具可读性...


1
很好,谢谢。我已经做的更好了。您有我的投票权,如果没有更好的选择,我很乐意在时间耗尽时将赏金转移给您。另外,我喜欢您的用户名。
埃里克(Eric Fail)2012年


15

R的 包也将执行此操作(来自?alluvial)。

# install.packages(c("alluvial"), dependencies = TRUE)
require(alluvial)

# Titanic data
tit <- as.data.frame(Titanic)

# 4d
alluvial( tit[,1:4], freq=tit$Freq, border=NA,
     hide = tit$Freq < quantile(tit$Freq, .50),
     col=ifelse( tit$Class == "3rd" & tit$Sex == "Male", "red", "gray") )

在此处输入图片说明



6

这些定义来看此功能(如并行集图)缺乏拆分和合并流(即通过多个转换)的能力。

由于Sankey图是有向加权图,因此qgraph之类的软件包可能会有用。

SankeyR如果您按降序对损失进行排序,则该功能将提供更清晰的标签,因为文本放置在靠近箭头的位置而没有重叠。


1
排序按降序排列的损失将打破图的定向质量。如果仔细查看我提交的图表,您会发现时间在x轴上,因此是当前顺序。我知道sankey-diagrams.com及其上的文章,当我看到该网站时,我首先想到的是打开op R并在ggplot2中生成一个漂亮的Sankey图。
埃里克失败

5

请访问//sankeybuilder.com,因为它提供了一个随时可用的解决方案,您可以在其中随时间上传数据和播放变化。过渡效果很好(类似于您问题中的youtube演示)。如果加载SankeyTrend演示,则它包含许多时隙(数据年)。加载后(自动生成sankey),单击页面右上角的播放按钮以播放时隙,您甚至可以暂停和恢复时间。演示网址在这里: SankeyTrend希望这可以帮助您寻求完美的Sankey图。


4

为了完整起见,还有 ggalluvialggplot2 extension用于冲积/桑基图软件包。

这是从软件包文档中获取的示例

# devtools::install_github("corybrunson/ggalluvial", ref = "optimization")
library(ggalluvial)

titanic_wide <- data.frame(Titanic)
ggplot(data = titanic_wide,
       aes(axis1 = Class, axis2 = Sex, axis3 = Age,
           y = Freq)) +
  scale_x_discrete(limits = c("Class", "Sex", "Age"), expand = c(.1, .05)) +
  xlab("Demographic") +
  geom_alluvium(aes(fill = Survived)) +
  geom_stratum() + geom_text(stat = "stratum", label.strata = TRUE) +
  theme_minimal() +
  ggtitle("passengers on the maiden voyage of the Titanic",
          "stratified by demographics and survival") +
  theme(legend.position = 'bottom')

ggplot(titanic_wide,
       aes(y = Freq,
           axis1 = Survived, axis2 = Sex, axis3 = Class)) +
  geom_alluvium(aes(fill = Class),
                width = 0, knot.pos = 0, reverse = FALSE) +
  guides(fill = FALSE) +
  geom_stratum(width = 1/8, reverse = FALSE) +
  geom_text(stat = "stratum", label.strata = TRUE, reverse = FALSE) +
  scale_x_continuous(expand = c(0, 0), 
                     breaks = 1:3, labels = c("Survived", "Sex", "Class")) +
  scale_y_discrete(expand = c(0, 0)) +
  coord_flip() +
  ggtitle("Titanic survival by class and sex")

reprex软件包(v0.2.1.9000)创建于2018-11-13


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.