Diagramas de Sankey em R?


86

Estou tentando visualizar meu fluxo de dados com um Diagrama de Sankey em R.

Eu encontrei esta postagem do blog com um link para um script R que produz um Diagrama de Sankey, infelizmente é bastante bruto e um tanto limitado (veja abaixo para exemplos de código e dados).

Alguém conhece outros scripts - ou talvez até mesmo um pacote - que seja mais desenvolvido? Meu objetivo final é visualizar o fluxo de dados e as porcentagens por tamanho relativo dos componentes do diagrama, como nesses exemplos de Diagramas de Sankey .

Eu postei uma pergunta um tanto semelhante na lista r-help , mas depois de duas semanas sem nenhuma resposta, estou tentando a sorte aqui no stackoverflow.

Obrigada Eric

PS. Estou ciente do gráfico de conjuntos paralelos , mas não é isso que estou procurando.

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

Diagrama de Sankey produzido com o código acima, Diagrama de Sankey produzido com o código acima


2
As setas parecem boas para mim, parece que você fez o ajuste fino do texto e está dentro?
Roman Luštrik

@Roman Luštrik, concordo, este diagrama não é nada mau, mas minhas habilidades em R ainda são limitadas, então não posso fazer muitos ajustes finos em R, se era isso que você quis dizer? Claro que poderia fazer no Adobe Illustrator, ou algo parecido, mas isso quebraria o princípio da pesquisa reproduzível, que para mim é um elemento central em qualquer trabalho (acadêmico). Você viu os exemplos que vinculei no post ?
Eric Fail,

Eu percebo que minha pergunta não é uma boa pergunta no sentido de que não é um problema de programação específico e não é diretamente prático, mas uma pergunta um tanto aberta ( do FAQ ). Para responder a esta pergunta, seria necessário supervisionar as diferentes opções de gráficos em R e, com base nisso, responder minha pergunta com um não, não há scripts ou pacotes mais desenvolvidos por aí , ou seria necessário saber de um método mais desenvolvido para produzir diagramas de Sankey em R e apontar para ele. Talvez haja um lugar melhor para postar esta pergunta?
Eric Fail

1
O único lugar que posso encontrar é talvez crossvalidated.com.
Roman Luštrik,

Que tal a lista de discussão R-help? r-project.org/mail.html
Alex Reynolds

Respostas:


63

Este gráfico pode ser criado por meio do networkD3pacote. Ele permite que você crie diagramas sankey interativos. Aqui você pode encontrar um exemplo . Também adicionei uma captura de tela para que você tenha uma ideia de como é.

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

insira a descrição da imagem aqui


4
link de exemplo quebrado
rmstmppr

1
De fato. Uma alternativa melhor desde a introdução do htmlwidgetsé o enredo sankey do networkD3pacote. Eu atualizei a postagem.
JT85 de

1
É possível ter valores numéricos como legenda em vez de inteiro? Os valores foram tomados corretamente, mas a legenda parece estar arredondada. Por exemplo: valor = 0,8 e valor = 0,2 têm larguras de linha diferentes, mas a legenda diz '0' para ambos.
Naveen Mathew

se você tentar reproduzir isso com alguma amostra de seus próprios dados, certifique-se de que o primeiro id de origem comece com 0 e os ids de origem e de destino sejam sucessivos
Richard

43

Eu criei um pacote ( riverplot ) que tem uma funcionalidade ligeiramente diferente, mas sobreposta em comparação com a função Sankey, e pode produzir gráficos como este:

insira a descrição da imagem aqui


Isso parece realmente impressionante! Vou dar uma olhada nisso o mais rápido possível.
Eric Fail,

39

Se você quiser fazer isso com R, seu melhor lance parece ser a sugestão @Roman - hackear a função SankeyR . Por exemplo - abaixo está minha solução muito rápida - simplesmente oriente os rótulos verticalmente, desloque-os ligeiramente e diminua a fonte para referências de entrada para torná-los um pouco melhor. Esta modificação altera apenas a linha 171 e 223 na função 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)

insira a descrição da imagem aqui

Não sou um craque em trigonometria, mas isso é realmente o que você precisa para mudar a direção das setas. Isso seria ideal na minha opinião - se você pudesse ajustar as setas soltas para que sejam orientadas horizontalmente em vez de verticalmente. Caso contrário, por que minha solução corrige o problema com a orientação dos rótulos, não torna o diagrama muito mais legível ...


1
isso é um bom hack, obrigado. Eu já fiz muito melhor. Você tem meu voto favorável e se nada melhor acontecer, fico feliz em transferir a recompensa para você quando o tempo acabar. Além disso, gosto do seu nome de usuário.
Eric Fail,

24

Além de rCharts , os diagramas de Sankey agora também podem ser gerados em R com googleVis (versão> = 0.5.0). Por exemplo, esta postagem descreve a geração do seguinte diagrama usando googleVis: insira a descrição da imagem aqui


15

R's pacote também fará isso (de ?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") )

insira a descrição da imagem aqui



6

Julgando por essas definições essa função, como o gráfico de conjuntos paralelos, não tem a capacidade de dividir e combinar fluxos (ou seja, por meio de mais de uma transição).

Visto que os diagramas Sankey são gráficos ponderados direcionados , um pacote como o qgraph pode ser útil.

A SankeyRfunção fornece rótulos mais claros se você classificar as perdas em ordem decrescente à medida que o texto é colocado próximo às pontas das setas sem se sobrepor.


1
Classificar as perdas em ordem decrescente quebraria a qualidade direcional do diagrama. Se você olhar atentamente para o diagrama que enviei, verá que o tempo está no eixo x, daí a ordem atual. Estou ciente de sankey-diagrams.com e dos artigos sobre ele, meu primeiro pensamento quando vi esse site foi abrir op R e produzir um diagrama de Sankey agradável em ggplot2 .
Eric Fail

5

dê uma olhada em //sankeybuilder.com, pois ele oferece uma solução pronta para usar, onde você pode carregar seus dados e reproduzir variações ao longo do tempo. A transição funciona bem (semelhante à demonstração do youtube em sua pergunta). Se você carregar a demonstração SankeyTrend, ela incluirá muitos intervalos de tempo (anos de dados). Uma vez carregado (cria sankeys automaticamente), clique no botão play no canto superior direito da página para reproduzir os slots de tempo, você pode até pausar e retomar o tempo. O URL de demonstração está aqui: SankeyTrend Espero que isso ajude sua busca pelo diagrama de Sankey perfeito.


4

Para ser completo, há também o ggalluvialpacote que é umggplot2 extension para diagramas aluviais / Sankey.

Aqui está um exemplo retirado da documentação do pacote

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

Criado em 13/11/2018 pelo pacote reprex (v0.2.1.9000)


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.