Sankey-Diagramme in R?


86

Ich versuche, meinen Datenfluss mit einem Sankey-Diagramm in R zu visualisieren.

Ich habe diesen Blog-Beitrag gefunden , der auf ein R-Skript verweist, das ein Sankey-Diagramm erstellt. Leider ist es ziemlich roh und etwas eingeschränkt (Beispielcode und Daten siehe unten).

Kennt jemand andere Skripte - oder vielleicht sogar ein Paket -, das weiter entwickelt ist? Mein Endziel ist es, sowohl den Datenfluss als auch die Prozentsätze nach relativer Größe der Diagrammkomponenten zu visualisieren, wie in diesen Beispielen für Sankey-Diagramme .

Ich habe eine ähnliche Frage auf der R- Hilfeliste gepostet , aber nach zwei Wochen ohne Antwort versuche ich mein Glück hier auf Stackoverflow.

Danke, Eric

PS. Ich kenne den Plot für parallele Mengen , aber das ist nicht das, wonach ich suche.

# 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-Diagramm mit dem obigen Code erstellt, Sankey-Diagramm mit dem obigen Code erstellt


2
Die Pfeile sehen für mich gut aus. Sieht so aus, als ob Sie den Text noch fein abstimmen müssen und dabei sind?
Roman Luštrik

@Roman Luštrik, ich stimme zu, dieses Diagramm ist überhaupt nicht schlecht, aber meine R-Fähigkeiten sind immer noch begrenzt, so dass ich nicht wirklich so viel Feinabstimmung in R vornehmen kann, wenn Sie das gemeint haben? Ich könnte es natürlich in Adobe Illustrator oder ähnlichem tun, aber das würde das Prinzip der reproduzierbaren Forschung brechen, das für mich ein zentrales Element in jeder (akademischen) Arbeit ist. Haben Sie sich die Beispiele angesehen , auf die ich im Beitrag verlinkt habe ?
Eric Fail

Mir ist klar, dass meine Frage keine gute Frage in dem Sinne ist, dass es sich nicht um ein spezifisches Programmierproblem handelt und nicht direkt praktisch ist, sondern um eine etwas offene Frage ( aus den FAQ ). Um diese Frage zu beantworten, müsste man entweder die verschiedenen Grafikoptionen in R im Auge behalten und auf dieser Basis meine Frage mit einem Nein beantworten , es gibt keine Skripte oder Pakete, die weiter entwickelt sind , oder man müsste a kennen weiterentwickelte Methode, um Sankey-Diagramme in R zu erstellen und darauf zu verweisen. Vielleicht gibt es einen besseren Ort, um diese Frage zu posten?
Eric Fail

1
Der einzige Ort, den ich finden kann, ist vielleicht crossvalidated.com.
Roman Luštrik

Wie wäre es mit der R-Hilfe-Mailingliste? r-project.org/mail.html
Alex Reynolds

Antworten:


63

Dieses Diagramm kann über das networkD3Paket erstellt werden. Sie können damit interaktive Sankey-Diagramme erstellen. Hier finden Sie ein Beispiel . Ich habe auch einen Screenshot hinzugefügt, damit Sie eine Vorstellung davon haben, wie es aussieht.

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

Geben Sie hier die Bildbeschreibung ein


4
Beispiel Link ist defekt
rmstmppr

1
Tatsächlich. Eine bessere Alternative seit Einführung htmlwidgetsist der Sankey-Plot aus dem networkD3Paket. Ich habe den Beitrag aktualisiert.
JT85

1
Ist es möglich, numerische Werte anstelle von Ganzzahlen als Beschriftung zu verwenden? Die Werte werden korrekt übernommen, aber die Beschriftung scheint abgerundet zu sein. Beispiel: Wert = 0,8 und Wert = 0,2 haben unterschiedliche Linienbreiten, aber die Beschriftung sagt für beide '0'.
Naveen Mathew

Wenn Sie versuchen, dies mit einem Beispiel Ihrer eigenen Daten zu reproduzieren, stellen Sie sicher, dass die erste Quell-ID mit 0 beginnt und die Quell- und Ziel-ID aufeinander
Richard

43

Ich habe ein Paket ( Riverplot ) erstellt, das im Vergleich zur Sankey-Funktion eine etwas andere, aber überlappende Funktionalität aufweist und Diagramme wie dieses erstellen kann:

Geben Sie hier die Bildbeschreibung ein


Das sieht wirklich beeindruckend aus! Ich werde es mir so schnell wie möglich ansehen.
Eric Fail

39

Wenn Sie es mit R tun möchten, scheint Ihr bestes Gebot @Roman Vorschlag zu sein - hacken Sie die SankeyR- Funktion. Zum Beispiel - unten ist meine sehr schnelle Lösung - richten Sie Beschriftungen einfach vertikal aus, versetzen Sie sie leicht und verringern Sie die Schriftart für Eingabeverweise, damit sie ein bisschen besser aussehen. Diese Änderung ändert nur die Zeilen 171 und 223 in der SankeyR- Funktion:

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

Geben Sie hier die Bildbeschreibung ein

Ich bin kein Ass in Trigonometrie, aber das ist wirklich das, was Sie brauchen, um die Richtung der Pfeile zu ändern. Das wäre aus meiner Sicht ideal - wenn Sie lose Pfeile so einstellen könnten, dass sie horizontal und nicht vertikal ausgerichtet sind. Wenn meine Lösung das Problem mit der Ausrichtung der Beschriftungen behebt, ist das Diagramm sonst nicht viel lesbarer ...


1
Das ist ein schöner Hack, danke. Ich habe es schon viel besser gemacht. Sie haben meine Stimme und wenn nichts Besseres eintritt, überweise ich Ihnen das Kopfgeld gerne, wenn die Zeit abgelaufen ist. Ich mag auch Ihren Benutzernamen.
Eric Fail

24

Zusätzlich zu rCharts können Sankey- Diagramme jetzt auch in R mit googleVis (Version> = 0.5.0) generiert werden . In diesem Beitrag wird beispielsweise die Erstellung des folgenden Diagramms mit googleVis beschrieben: Geben Sie hier die Bildbeschreibung ein


15

Rs Paket wird dies auch tun (von ?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") )

Geben Sie hier die Bildbeschreibung ein



6

Nach diesen Definitionen zu urteilen , fehlt dieser Funktion wie dem Diagramm der parallelen Mengen die Fähigkeit, Flüsse zu teilen und zu kombinieren (dh durch mehr als einen Übergang).

Da es sich bei Sankey-Diagrammen um gerichtete gewichtete Diagramme handelt , kann ein Paket wie qgraph hilfreich sein.

Die SankeyRFunktion bietet klarere Beschriftungen, wenn Sie die Verluste in absteigender Reihenfolge sortieren, wenn der Text näher an den Pfeilspitzen platziert wird, ohne sich zu überlappen.


1
Das Sortieren der Verluste in absteigender Reihenfolge würde die Richtungsqualität des Diagramms beeinträchtigen. Wenn Sie sich das von mir eingereichte Diagramm genau ansehen, werden Sie feststellen, dass die Zeit auf der x-Achse liegt, daher die aktuelle Reihenfolge. Ich kenne sankey-diagrams.com und die Artikel darauf. Mein erster Gedanke, als ich diese Website sah, war, op R zu öffnen und ein schönes Sankey-Diagramm in ggplot2 zu erstellen .
Eric Fail

5

Werfen Sie einen Blick auf //sankeybuilder.com, da es eine sofort einsatzbereite Lösung bietet, mit der Sie Ihre Daten hochladen und Variationen im Laufe der Zeit wiedergeben können. Der Übergang funktioniert gut (ähnlich der Youtube-Demo in Ihrer Frage). Wenn Sie die SankeyTrend-Demo laden, enthält sie viele Zeitfenster (Datenjahre). Klicken Sie nach dem Laden (erstellt Sankeys automatisch) auf die Wiedergabetaste in der oberen rechten Ecke der Seite, um die Zeitfenster wiederzugeben. Sie können sogar die Zeit anhalten und fortsetzen. Die Demo-URL ist hier: SankeyTrend Hoffe, dies hilft Ihnen bei der Suche nach dem perfekten Sankey-Diagramm.


4

Der Vollständigkeit halber gibt es auch das ggalluvialPaket ggplot2 extensionfür alluviale / Sankey-Diagramme.

Hier ist ein Beispiel aus der Dokumentation des Pakets

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

Erstellt am 13.11.2018 vom reprex-Paket (v0.2.1.9000)


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.