Diagramy Sankeya w R?

87

Próbuję zwizualizować mój przepływ danych za pomocą diagramu Sankeya w R.

Znalazłem ten post na blogu z linkiem do skryptu R, który tworzy diagram Sankeya, niestety jest dość surowy i nieco ograniczony (zobacz poniżej przykładowy kod i dane).

Czy ktoś zna inne skrypty - a może nawet pakiet - który jest bardziej rozbudowany? Moim końcowym celem jest wizualizacja zarówno przepływu danych, jak i wartości procentowych za pomocą względnego rozmiaru komponentów diagramu, jak w tych przykładach diagramów Sankeya .

Opublikowałem trochę podobne pytanie na liście r-help , ale po dwóch tygodniach bez żadnej odpowiedzi próbuję szczęścia tutaj na stackoverflow.

Dzięki, Eric

PS. Jestem świadomy fabuły zestawów równoległych , ale nie tego szukam.

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

Diagram Sankeya utworzony z powyższego kodu, Diagram Sankeya utworzony przy użyciu powyższego kodu

Eric Fail
źródło
2
Strzały wyglądają dobrze, wygląda na to, że zostałeś z dopracowaniem tekstu i jesteś w środku?
Roman Luštrik
@Roman Luštrik, zgadzam się, ten schemat wcale nie jest zły, ale moje umiejętności R są nadal ograniczone, więc naprawdę nie mogę zrobić tak dużo dostrojenia w R, jeśli o to ci chodziło? Mógłbym oczywiście zrobić to w programie Adobe Illustrator lub czymś podobnym, ale to złamałoby zasadę powtarzalnych badań, która jest dla mnie centralnym elementem każdej pracy (naukowej). Czy spojrzałeś na przykłady, do których umieściłem łącze w poście ?
Eric Fail
Zdaję sobie sprawę, że moje pytanie nie jest dobrym pytaniem w tym sensie, że nie jest to konkretny problem programistyczny i nie jest bezpośrednio praktyczny, ale raczej otwarte ( z FAQ ). Aby odpowiedzieć na to pytanie, należałoby albo mieć nadzór nad różnymi opcjami graficznymi w R i na tej podstawie odpowiedzieć na moje pytanie nie, nie ma tam żadnych bardziej rozwiniętych skrawków ani pakietu , albo należałoby wiedzieć bardziej rozwinięta metoda tworzenia diagramów Sankeya w R i wskazywania na to. Może jest lepsze miejsce do zadawania tego pytania?
Eric Fail
1
Jedyne miejsce, które mogę wymyślić, to może crossvalidated.com.
Roman Luštrik
A co z listą mailingową R-help? r-project.org/mail.html
Alex Reynolds

Odpowiedzi:

63

Ten wykres można utworzyć za pomocą networkD3pakietu. Pozwala na tworzenie interaktywnych diagramów Sankeya. Tutaj możesz znaleźć przykład . Dodałem też zrzut ekranu, więc masz pojęcie, jak to wygląda.

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

wprowadź opis obrazu tutaj

Jonas Tundo
źródło
4
przykładowy link jest uszkodzony
rmstmppr
1
W rzeczy samej. Lepszą alternatywą od wprowadzenia htmlwidgetsjest fabuła Sankey z networkD3pakietu. Zaktualizowałem post.
Jonas Tundo
1
Czy w podpisie można umieścić wartości liczbowe zamiast liczb całkowitych? Wartości są brane poprawnie, ale podpis wydaje się być zaokrąglony. Np. Wartość = 0,8 i wartość = 0,2 mają różne szerokości linii, ale podpis mówi „0” dla obu.
Naveen Mathew
jeśli spróbujesz odtworzyć to z jakąś próbką własnych danych, upewnij się, że pierwszy identyfikator źródła zaczyna się od 0, a identyfikatory źródła i celu są następujące po sobie
Richard
43

Utworzyłem pakiet ( riverplot ), który ma nieco inną, ale nakładającą się funkcjonalność w porównaniu z funkcją Sankey i może tworzyć wykresy takie jak ta:

wprowadź opis obrazu tutaj

styczeń
źródło
To wygląda naprawdę imponująco! Rzucę okiem na to jak najszybciej.
Eric Fail,
39

Jeśli chcesz to zrobić z R, najlepszą ofertą wydaje się być sugestia @Roman - zhakuj funkcję SankeyR . Na przykład - poniżej znajduje się moja bardzo szybka poprawka - po prostu ustaw etykiety pionowo, nieznacznie je przesuń i zmniejsz czcionkę dla odnośników wejściowych, aby wyglądała trochę lepiej. Ta modyfikacja zmienia tylko linie 171 i 223 w funkcji SankeyR :

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

wprowadź opis obrazu tutaj

Nie jestem asem w trygonometrii, ale tak naprawdę to jest to, czego potrzebujesz, aby zmienić kierunek strzałek. Moim zdaniem byłoby to idealne - gdybyś mógł wyregulować strzałki luźne tak, aby były zorientowane poziomo, a nie pionowo. W przeciwnym razie, dlaczego moje rozwiązanie rozwiązuje problem z orientacją etykiet, nie czyni diagramu bardziej czytelnym ...

Geek On Acid
źródło
1
to niezły hack, dzięki. Już to zrobiłem znacznie lepiej. Masz moją pozytywną opinię i jeśli nic lepszego nie wyjdzie, z radością przekażę ci nagrodę, gdy skończy się czas. Podoba mi się również twoja nazwa użytkownika.
Eric Fail
24

Oprócz rCharts , diagramy Sankey można teraz generować również w języku R za pomocą googleVis (wersja> = 0.5.0). Na przykład ten post opisuje sposób generowania poniższego diagramu za pomocą googleVis: wprowadź opis obrazu tutaj

leo9r
źródło
15

R's pakiet również to zrobi (z ?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") )

wprowadź opis obrazu tutaj

geoteoria
źródło
6

Sądząc po tych definicjach, tej funkcji, podobnie jak wykresu zbiorów równoległych, brakuje możliwości dzielenia i łączenia przepływów (tj. Przez więcej niż jedno przejście).

Ponieważ diagramy Sankeya są ukierunkowanymi wykresami ważonymi , pakiet taki jak qgraph może być przydatny.

Ta SankeyRfunkcja zapewnia wyraźniejsze etykiety, jeśli posortujesz straty w porządku malejącym, ponieważ tekst jest umieszczony bliżej grotów strzałek bez nakładania się.

RobinGower
źródło
1
Uporządkowanie strat w porządku malejącym mogłoby zepsuć kierunkową jakość diagramu. Jeśli przyjrzysz się uważnie diagramowi, który przesłałem, zobaczysz, że czas jest na osi X, stąd obecna kolejność. Jestem świadomy sankey-diagrams.com i artykułów na nim, moją pierwszą myślą, kiedy zobaczyłem tę stronę, było otwarcie op R i stworzenie ładnego diagramu Sankey w ggplot2 .
Eric Fail
5

zajrzyj na //sankeybuilder.com, ponieważ oferuje gotowe rozwiązanie, w którym możesz przesyłać swoje dane i zmiany odtwarzania w czasie. Przejście działa dobrze (podobnie do dema youtube w twoim pytaniu). Jeśli załadujesz demo SankeyTrend, zawiera ono wiele przedziałów czasowych (lata danych). Po załadowaniu (automatycznie buduje sankeys), kliknij przycisk odtwarzania w prawym górnym rogu strony, aby odtworzyć przedziały czasowe, możesz nawet wstrzymać i wznowić czas. Demo URL jest tutaj: SankeyTrend Mam nadzieję, że pomoże to w poszukiwaniu idealnego diagramu Sankey.

Obrabować
źródło
4

Dla kompletności istnieje również ggalluvialpakiet, który jest ggplot2 extensiondla diagramów aluwialnych / Sankeya.

Oto przykład zaczerpnięty z dokumentacji pakietu

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

Utworzono 13.11.2018 r. Przez pakiet reprex (v0.2.1.9000)

Tung
źródło
1

Wystarczy otworzyć pakiet źródłowy, który wykorzystuje diagram aluwialny do wizualizacji etapów przepływu pracy. Ponieważ w przypadku form aluwialnych zachowuje się historię, na brzegach nie ma skrzyżowań.

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

wprowadź opis obrazu tutaj

Clayton Stanley
źródło