桑基图 R?

我试图用 R 中的桑基图来可视化我的数据流。

我发现 这篇博文链接到一个生成 Sankey Diagram 的 R 脚本; 不幸的是,它非常原始,而且有些局限(参见下面的示例代码和数据)。

有人知道其他更成熟的脚本(或者甚至包)吗?我的最终目标是通过图表组件的相对大小来可视化数据流和百分比,就像在 这些桑基图的例子中一样。

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

谢谢, 艾瑞克

另外,我知道 平行集图但那不是我要找的。

# 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 Diagram produced with the code above

55338 次浏览

Judging by these definitions this function, like the Parallel Sets Plot, lacks the capacity to split and combine flows (i.e. through more than one transition).

Since Sankey diagrams are directed weighted graphs, a package like qgraph might be useful.

The SankeyR function provides clearer labels if you sort the losses in descending order as the text is placed closer to the arrow heads without overlapping.

If you want to do it with R, your best bid seems to be @Roman suggestion - hack the SankeyR function. For example - below is my very quick fix - simply orient labels verticaly, slighlty offset them and decrease the font for input referals to make it look a bit better. This modification only changes line 171 and 223 in the SankeyR function:

    #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)

enter image description here

I am no ace in trigonometry, but this is really what you need for changing the direction of arrows. That would be ideal in my view - if you could adjust looses arrows so they are oriented horizontally rather then vertically. Otherwise, why my solution fixes the problem with labels orientation, it doesn't make the diagram much more readable...

I have created a package (riverplot) that has a slightly different, but overlapping functionality compared to the Sankey function, and can produce plots like this one:

enter image description here

This plot can be created through the networkD3 package. It allows you to create interactive sankey diagrams. Here you can find an example. I also added a screenshot so you have an idea what it looks like.

# 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)

enter image description here

In addition to rCharts, Sankey diagrams can now be also generated in R with googleVis (version >= 0.5.0). For example, this post describes the generation of the following diagram using googleVis: enter image description here

have a look at //sankeybuilder.com as it offers a ready to go solution where you can upload your data and playback variations over time. The transition works well (similar to the youtube demo in your question). If you load the SankeyTrend demo it includes many time slots (Years of data). Once loaded (builds sankeys automatically), click the play button in the upper right hand corner of the page for playback of the time slots, you can even pause and resume time. Demo url is here: SankeyTrend Hope this helps your quest for the perfect Sankey diagram.

R's package will also do this (from ?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") )

enter image description here

plotly has the same power as networkD3 package (example link).

enter image description here

Just open sourced a package that uses an alluvial diagram to visualize workflow stages. Since history is kept when the alluvial form is used, there aren't any crossovers in the edges.

https://github.com/claytontstanley/shiny.alluvial

enter image description here

For completeness, there is also the ggalluvial package which is a ggplot2 extension for alluvial/Sankey diagrams.

Here is an example taken from the package's documentation

# 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")

Created on 2018-11-13 by the reprex package (v0.2.1.9000)