Sankey Diagrams ใน R?


89

ฉันกำลังพยายามนึกภาพการไหลของข้อมูลด้วย Sankey Diagram ใน R

ฉันพบว่าบล็อกโพสต์นี้เชื่อมโยงกับสคริปต์ R ที่สร้าง Sankey Diagram แต่น่าเสียดายที่มันค่อนข้างดิบและค่อนข้าง จำกัด (ดูโค้ดตัวอย่างและข้อมูลด้านล่าง)

มีใครรู้จักสคริปต์อื่น ๆ หรืออาจจะเป็นแพ็คเกจที่พัฒนามากกว่านี้บ้าง? เป้าหมายสุดท้ายของฉันคือการเห็นภาพทั้งการไหลของข้อมูลและเปอร์เซ็นต์ตามขนาดสัมพัทธ์ของส่วนประกอบไดอะแกรมเช่นในตัวอย่าง Sankey Diagramsเหล่านี้

ฉันโพสต์คำถามที่ค่อนข้างคล้ายกันในรายการ r-helpแต่หลังจากผ่านไปสองสัปดาห์โดยไม่มีคำตอบใด ๆ ฉันกำลังพยายามเสี่ยงโชคที่นี่ใน stackoverflow

ขอบคุณเอริค

ปล. ฉันรู้เรื่องParallel Sets Plotแต่นั่นไม่ใช่สิ่งที่ฉันกำลังมองหา

# 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 ผลิตด้วยรหัสด้านบน Sankey Diagram ผลิตด้วยรหัสด้านบน


2
ลูกศรดูดีสำหรับฉันดูเหมือนว่าคุณจะถูกปรับแต่งข้อความอย่างละเอียดและคุณเข้ามา?
Roman Luštrik

@ Roman Luštrikฉันเห็นด้วยแผนภาพนี้ไม่เลวเลย แต่ทักษะ R ของฉันยังมี จำกัด ดังนั้นฉันจึงไม่สามารถปรับแต่ง R ให้ละเอียดได้มากนักถ้านั่นคือสิ่งที่คุณหมายถึง? แน่นอนว่าฉันสามารถทำได้ใน Adobe Illustrator หรืออะไรทำนองนั้น แต่นั่นจะทำลายหลักการของการวิจัยที่ทำซ้ำได้ซึ่งสำหรับฉันแล้วถือเป็นองค์ประกอบสำคัญในงานวิชาการใด ๆ คุณดูตัวอย่างที่ฉันลิงก์ไว้ในโพสต์หรือไม่
Eric Fail

ฉันตระหนักดีว่าคำถามของฉันไม่ใช่คำถามที่ดีในแง่ที่ว่าไม่ใช่ปัญหาการเขียนโปรแกรมที่เฉพาะเจาะจงและไม่สามารถใช้งานได้จริง แต่เป็นคำถามปลายเปิด ( จากคำถามที่พบบ่อย ) ในการตอบคำถามนี้เราจะต้องมีการกำกับดูแลตัวเลือกการสร้างกราฟที่แตกต่างกันใน R และบนพื้นฐานนั้นตอบคำถามของฉันด้วยไม่ไม่มี scrips หรือแพ็คเกจใด ๆ ที่มีการพัฒนามากกว่านี้หรือต้องรู้ a วิธีการที่พัฒนามากขึ้นในการสร้าง Sankey Diagrams ใน R และชี้ไปที่มัน อาจมีสถานที่ที่ดีกว่าในการโพสต์คำถามนี้?
Eric Fail

1
สถานที่เดียวที่ฉันสามารถหาได้คือ crossvalidated.com
Roman Luštrik

แล้วรายชื่อผู้รับจดหมาย R-help ล่ะ? r-project.org/mail.html
Alex Reynolds

คำตอบ:


63

พล็อตนี้สามารถสร้างผ่านnetworkD3แพ็คเกจ ช่วยให้คุณสร้างแผนภาพ sankey แบบโต้ตอบได้ คุณสามารถดูตัวอย่างได้ที่นี่ ฉันยังเพิ่มภาพหน้าจอเพื่อให้คุณมีความคิดว่ามันเป็นอย่างไร

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

ใส่คำอธิบายภาพที่นี่


4
ลิงค์ตัวอย่างเสีย
rmstmppr

1
แน่นอน. ทางเลือกที่ดีกว่าเนื่องจากการแนะนำhtmlwidgetsคือพล็อตเรื่องตลกจากnetworkD3แพ็คเกจ ผมปรับปรุงโพสต์
Jonas Tundo

1
เป็นไปได้ไหมที่จะมีค่าตัวเลขเป็นคำอธิบายภาพแทนที่จะเป็นจำนวนเต็ม ค่าต่างๆถูกนำมาใช้อย่างถูกต้อง แต่ดูเหมือนว่าคำอธิบายภาพจะถูกปัดเศษออก เช่น value = 0.8 และ value = 0.2 มีความกว้างของเส้นต่างกัน แต่คำบรรยายระบุว่า "0" สำหรับทั้งสองอย่าง
Naveen Mathew

หากคุณพยายามทำซ้ำสิ่งนี้กับตัวอย่างข้อมูลของคุณเองตรวจสอบให้แน่ใจว่ารหัสแหล่งแรกเริ่มต้นด้วย 0 และรหัสแหล่งที่มาและเป้าหมายจะต่อเนื่องกัน
Richard

43

ฉันได้สร้างแพ็คเกจ ( ริเวอร์พล็อต ) ที่มีฟังก์ชันการทำงานที่แตกต่างกันเล็กน้อย แต่ทับซ้อนกันเมื่อเทียบกับฟังก์ชัน Sankey และสามารถสร้างพล็อตเช่นนี้ได้:

ใส่คำอธิบายภาพที่นี่


ดูน่าประทับใจจริงๆ! ฉันจะดูโดยเร็ว
Eric Fail

39

หากคุณต้องการใช้ R การเสนอราคาที่ดีที่สุดของคุณน่าจะเป็นคำแนะนำของ @Roman - แฮ็กฟังก์ชันSankeyR ตัวอย่างเช่น - ด้านล่างนี้คือการแก้ไขอย่างรวดเร็วของฉันเพียงแค่ปรับทิศทางป้ายตามแนวตั้งให้เอียงชดเชยและลดแบบอักษรสำหรับการอ้างอิงการป้อนข้อมูลเพื่อให้ดูดีขึ้นเล็กน้อย การปรับเปลี่ยนนี้เปลี่ยนเฉพาะบรรทัด 171 และ 223 ในฟังก์ชัน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)

ใส่คำอธิบายภาพที่นี่

ฉันไม่ใช่เอซในตรีโกณมิติ แต่นี่คือสิ่งที่คุณต้องการสำหรับการเปลี่ยนทิศทางของลูกศร นั่นจะเหมาะมากในมุมมองของฉัน - ถ้าคุณสามารถปรับลูกศรที่หายไปเพื่อให้พวกมันวางในแนวนอนแทนที่จะเป็นแนวตั้ง มิฉะนั้นทำไมโซลูชันของฉันจึงแก้ไขปัญหาเกี่ยวกับการวางแนวฉลากได้จึงไม่ทำให้แผนภาพอ่านง่ายขึ้น ...


1
เป็นการแฮ็คที่ดีขอบคุณ ฉันทำได้ดีขึ้นมากแล้ว คุณมีคะแนนโหวตของฉันและถ้าไม่มีอะไรดีขึ้นมาฉันยินดีที่จะโอนเงินรางวัลให้คุณเมื่อเวลาหมดลง นอกจากนี้ฉันชอบชื่อผู้ใช้ของคุณ
Eric Fail

24

นอกจากนี้ในการrCharts , แซนคีย์ไดอะแกรมสามารถตอนนี้ถูกสร้างขึ้นยังอยู่ใน R กับgoogleVis (รุ่น> = 0.5.0) ตัวอย่างเช่นโพสต์นี้อธิบายการสร้างไดอะแกรมต่อไปนี้โดยใช้ googleVis: ใส่คำอธิบายภาพที่นี่


15

อาร์ แพ็คเกจจะทำสิ่งนี้ด้วย (จาก?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") )

ใส่คำอธิบายภาพที่นี่



6

การตัดสินโดยคำจำกัดความเหล่านี้ฟังก์ชันนี้เช่น Parallel Sets Plot ขาดความสามารถในการแยกและรวมโฟลว์ (เช่นผ่านการเปลี่ยนแปลงมากกว่าหนึ่งครั้ง)

เนื่องจากแผนภาพ Sankey เป็นกราฟถ่วงน้ำหนักแพคเกจเช่นqgraphอาจมีประโยชน์

SankeyRฟังก์ชั่นให้ฉลากชัดเจนถ้าคุณเรียงลำดับการสูญเสียในลำดับถัดลงมาเป็นข้อความที่ถูกวางไว้ใกล้ชิดกับหัวลูกศรโดยไม่ทับซ้อนกัน


1
การเรียงลำดับการสูญเสียจากมากไปหาน้อยจะทำลายคุณภาพทิศทางของแผนภาพ หากคุณดูแผนภาพที่ฉันส่งมาอย่างละเอียดคุณจะเห็นว่าเวลานั้นอยู่บนแกน x ดังนั้นลำดับปัจจุบัน ฉันรู้sankey-diagrams.comและบทความเกี่ยวกับมันความคิดแรกของฉันเมื่อฉันเห็นเว็บไซต์ที่กำลังจะเปิดสหกรณ์ R และการผลิตที่ดีแซนคีย์แผนภาพในggplot2
Eric Fail

5

ดูที่//sankeybuilder.comเนื่องจากมีโซลูชันที่พร้อมใช้งานซึ่งคุณสามารถอัปโหลดข้อมูลและรูปแบบการเล่นได้ตลอดเวลา การเปลี่ยนแปลงทำงานได้ดี (คล้ายกับการสาธิต YouTube ในคำถามของคุณ) หากคุณโหลดการสาธิต SankeyTrend จะมีช่วงเวลามากมาย (ปีของข้อมูล) เมื่อโหลดแล้ว (สร้าง sankeys โดยอัตโนมัติ) ให้คลิกปุ่มเล่นที่มุมขวาบนของหน้าเพื่อเล่นช่วงเวลาคุณสามารถหยุดชั่วคราวและเล่นต่อได้ URL สาธิตอยู่ที่นี่: SankeyTrendหวังว่านี่จะช่วยในการแสวงหาแผนภาพ Sankey ที่สมบูรณ์แบบ


4

เพื่อความสมบูรณ์นอกจากนี้ยังมีggalluvialแพ็คเกจซึ่งเป็นggplot2 extensionไดอะแกรมสำหรับ alluvial / Sankey

นี่คือตัวอย่างที่นำมาจากเอกสารของแพ็คเกจ

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

สร้างเมื่อ 2018-11-13 โดยแพ็คเกจ reprex (v0.2.1.9000)


1

เพียงแค่เปิดแพคเกจที่มาที่ใช้แผนภาพ alluvial เพื่อแสดงภาพขั้นตอนเวิร์กโฟลว์ เนื่องจากประวัติจะถูกเก็บไว้เมื่อใช้รูปแบบ alluvial จึงไม่มีการไขว้ที่ขอบ

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

ใส่คำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.