Diagramas de Sankey en R?

86

Estoy tratando de visualizar mi flujo de datos con un diagrama de Sankey en R.

Encontré esta publicación de blog enlazada a un script R que produce un Diagrama de Sankey, desafortunadamente es bastante crudo y algo limitado (vea a continuación el código y los datos de muestra).

¿Alguien sabe de otros scripts, o tal vez incluso de un paquete, que esté más desarrollado? Mi objetivo final es visualizar tanto el flujo de datos como los porcentajes por tamaño relativo de los componentes del diagrama, como en estos ejemplos de diagramas de Sankey .

Publiqué una pregunta algo similar en la lista de r-help , pero después de dos semanas sin ninguna respuesta, estoy probando suerte aquí en stackoverflow.

Gracias Eric

PD. Soy consciente de la trama de conjuntos paralelos , pero eso no es lo que estoy buscando.

# 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 producido con el código anterior, Diagrama de Sankey producido con el código anterior

Eric Fail
fuente
2
Las flechas se ven bien para mí, parece que te quedaste con el ajuste fino del texto y estás dentro.
Roman Luštrik
@Roman Luštrik, estoy de acuerdo, este diagrama no está nada mal, pero mis habilidades de R aún son limitadas, así que realmente no puedo hacer tantos ajustes en R, si eso es lo que querías decir. Por supuesto, podría hacerlo en Adobe Illustrator, o algo parecido, pero eso rompería el principio de investigación reproducible, que para mí es un elemento central en cualquier trabajo (académico). ¿Miraste los ejemplos a los que he vinculado en la publicación ?
Eric Fail
Me doy cuenta de que mi pregunta no es una buena pregunta en el sentido de que no es un problema de programación específico y no es directamente práctico, sino una pregunta algo abierta ( de las Preguntas frecuentes ). Para responder a esta pregunta, uno tendría que tener supervisión sobre las diferentes opciones de gráficos en R y, sobre esa base, responder a mi pregunta con un no, no hay scripts o paquetes que estén más desarrollados , o se necesitaría conocer un método más desarrollado para producir diagramas de Sankey en R y señalarlo. ¿Quizás hay un mejor lugar para publicar esta pregunta?
Eric Fail
1
El único lugar que se me ocurre es quizás crossvalidated.com.
Roman Luštrik
¿Qué tal la lista de correo de R-help? r-project.org/mail.html
Alex Reynolds

Respuestas:

63

Este gráfico se puede crear a través del networkD3paquete. Le permite crear diagramas sankey interactivos. Aquí puede encontrar un ejemplo . También agregué una captura de pantalla para que tengas una idea de cómo se ve.

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

ingrese la descripción de la imagen aquí

Jonas Tundo
fuente
4
ejemplo de enlace roto
rmstmppr
1
En efecto. Una mejor alternativa desde la introducción de htmlwidgetses la parcela Sankey del networkD3paquete. Actualicé la publicación.
Jonas Tundo
1
¿Es posible tener valores numéricos como título en lugar de entero? Los valores se toman correctamente, pero el título parece estar redondeado. Por ejemplo: value = 0.8 y value = 0.2 tienen diferentes anchos de línea, pero el título dice '0' para ambos.
Naveen Mathew
si intenta reproducir esto con alguna muestra de sus propios datos, asegúrese de que la primera identificación de origen comience con 0 y que las identificaciones de origen y destino sean sucesivas
Richard
43

He creado un paquete ( riverplot ) que tiene una funcionalidad ligeramente diferente, pero superpuesta, en comparación con la función Sankey, y puede producir gráficos como este:

ingrese la descripción de la imagen aquí

enero
fuente
¡Esto se ve realmente impresionante! Lo echaré un vistazo lo antes posible.
Eric Fail
39

Si quieres hacerlo con R, tu mejor oferta parece ser la sugerencia de @Roman: hackear la función SankeyR . Por ejemplo, a continuación se muestra mi solución muy rápida: simplemente orientar las etiquetas verticalmente, desplazarlas ligeramente y disminuir la fuente para las referencias de entrada para que se vea un poco mejor. Esta modificación solo cambia las líneas 171 y 223 en la función 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)

ingrese la descripción de la imagen aquí

No soy un experto en trigonometría, pero esto es realmente lo que necesitas para cambiar la dirección de las flechas. Eso sería ideal en mi opinión, si pudiera ajustar las flechas sueltas para que estén orientadas horizontalmente en lugar de verticalmente. De lo contrario, la razón por la que mi solución soluciona el problema con la orientación de las etiquetas no hace que el diagrama sea mucho más legible ...

Friki del ácido
fuente
1
es un buen truco, gracias. Ya lo hice mucho mejor. Tienes mi voto a favor y si no surge nada mejor, me complacerá transferirte la recompensa cuando se acabe el tiempo. Además, me gusta tu nombre de usuario.
Eric Fail
24

Además de rCharts , los diagramas de Sankey ahora también se pueden generar en R con googleVis (versión> = 0.5.0). Por ejemplo, esta publicación describe la generación del siguiente diagrama usando googleVis: ingrese la descripción de la imagen aquí

leo9r
fuente
15

R's paquete también hará esto (desde ?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") )

ingrese la descripción de la imagen aquí

geoteoria
fuente
6

A juzgar por estas definiciones, esta función, como el gráfico de conjuntos paralelos, carece de capacidad para dividir y combinar flujos (es decir, a través de más de una transición).

Dado que los diagramas de Sankey son gráficos ponderados dirigidos , un paquete como qgraph puede resultar útil.

La SankeyRfunción proporciona etiquetas más claras si clasifica las pérdidas en orden descendente a medida que el texto se coloca más cerca de las puntas de las flechas sin superponerse.

RobinGower
fuente
1
Ordenar las pérdidas en orden descendente rompería la calidad direccional del diagrama. Si observa detenidamente el diagrama que envié, verá que el tiempo está en el eje x, de ahí el orden actual. Soy consciente de sankey-diagrams.com y de los artículos que contiene , lo primero que pensé cuando vi ese sitio web fue abrir op R y producir un buen diagrama de Sankey en ggplot2 .
Eric Fail
5

eche un vistazo a //sankeybuilder.com, ya que ofrece una solución lista para usar donde puede cargar sus datos y variaciones de reproducción a lo largo del tiempo. La transición funciona bien (similar a la demostración de YouTube en su pregunta). Si carga la demostración de SankeyTrend, incluye muchas franjas horarias (años de datos). Una vez cargado (construye sankeys automáticamente), haga clic en el botón de reproducción en la esquina superior derecha de la página para reproducir los intervalos de tiempo, incluso puede pausar y reanudar el tiempo. La URL de demostración está aquí: SankeyTrend Espero que esto ayude en su búsqueda del diagrama de Sankey perfecto.

Robar
fuente
4

Para completar, también está el ggalluvialpaquete que es ggplot2 extensionpara diagramas aluviales / Sankey.

Aquí hay un ejemplo tomado de la documentación del paquete.

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

Creado el 2018-11-13 por el paquete reprex (v0.2.1.9000)

Tung
fuente
1

Simplemente abrió un paquete que utiliza un diagrama aluvial para visualizar las etapas del flujo de trabajo. Dado que la historia se mantiene cuando se usa la forma aluvial, no hay cruces en los bordes.

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

ingrese la descripción de la imagen aquí

Clayton Stanley
fuente