Skip to content

Instantly share code, notes, and snippets.

@evaristoc
Last active February 21, 2016 14:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evaristoc/2d6c4f8c06c64768f119 to your computer and use it in GitHub Desktop.
Save evaristoc/2d6c4f8c06c64768f119 to your computer and use it in GitHub Desktop.
Sankey Diagram for camper curriculum paths (Feb-Mar 2015)

##Sankey Diagram for camper curriculum paths (Feb-Mar 2015).

This is an example of a Sankey diagram made using d3.js and the sankey plugin (2015).

The project points to campers who started at any point within the period of Feb-Mar 2015 and what they achieved before the period ended (Mar 31, PST).

The data is sorced from the Torrent Dataset being part of the Open Data initiative at FreeCodeCamp. Each node represent a step where they solved a challenge of the curriculum. Data for possible backs into previous steps was ignored.

Nodes are named as step + _ + challenge-code.

challenge-code are traslated as:

  • --->>> 0init
  • BA --->>> Binary Agents
  • Bw --->>> Boo who
  • CR --->>> Cash Register
  • CfP --->>> Check for Palindromes
  • CM --->>> Chunky Monkey
  • CtE --->>> Confirm the Ending
  • CHE --->>> Convert HTML Entities
  • DTA --->>> Diff Two Arrays
  • Dilih --->>> Drop it like it's hot
  • EBT --->>> Everything Be True
  • FaN --->>> Factorialize a Number
  • FB --->>> Falsey Bouncer
  • FtLWiaS --->>> Find the Longest Word in a String
  • FK --->>> Finders Keepers
  • IU --->>> Inventory Update
  • MaP --->>> Make a Person
  • MtD --->>> Map the Debris
  • MB --->>> Meet Bonfire
  • Ml --->>> Missing letters
  • M --->>> Mutations
  • Nrp --->>> No repeats please
  • P --->>> Pairwise
  • Rasras --->>> Repeat a string repeat a string
  • RLNiA --->>> Return Largest Numbers in Arrays
  • RaS --->>> Reverse a String
  • SaD --->>> Seek and Destroy
  • SF --->>> Slasher Flick
  • SCM --->>> Smallest Common Multiple
  • SU --->>> Sorted Union
  • STC --->>> Spinal Tap Case
  • S --->>> Steamroller
  • SANiaR --->>> Sum All Numbers in a Range
  • SAOFN --->>> Sum All Odd Fibonacci Numbers
  • SAP --->>> Sum All Primes
  • SD --->>> Symmetric Difference
  • TCaS --->>> Title Case a Sentence
  • Tas --->>> Truncate a string
  • VUTN --->>> Validate US Telephone Numbers
  • Wat --->>> Where art thou
  • WdIb --->>> Where do I belong

The data and coding are not totally revised so it is more for example purposes. A short discussion about this project could be found at https://gitter.im/FreeCodeCamp/DataScience.

The nodes can be moved horizontally and vertically. Open in full window for full effect.

This work started as fork of https://gist.github.com/d3noob/5028304. Description of how it was put together and techniques for implimenting Sankey diagrams in general with d3.js can be found at d3noob.org or you can download the full text in the D3 Tips and Tricks book (for free) from Leanpub.

{"links": [{"target": "32_VUTN", "source": "31_MtD", "value": 3}, {"target": "27_M", "source": "26_Dilih", "value": 1}, {"target": "7_CtE", "source": "6_RLNiA", "value": 82}, {"target": "19_SaD", "source": "18_STC", "value": 1}, {"target": "31_EBT", "source": "30_BA", "value": 1}, {"target": "24_SCM", "source": "23_SAP", "value": 12}, {"target": "20_CHE", "source": "19_SU", "value": 3}, {"target": "3_FaN", "source": "2_CfP", "value": 1}, {"target": "26_SCM", "source": "25_SAP", "value": 24}, {"target": "4_FtLWiaS", "source": "3_FaN", "value": 1}, {"target": "28_BA", "source": "27_S", "value": 6}, {"target": "0_MB", "source": "_", "value": 267}, {"target": "16_Wat", "source": "15_FB", "value": 1}, {"target": "10_CtE", "source": "9_SAP", "value": 2}, {"target": "34_EBT", "source": "33_Nrp", "value": 1}, {"target": "36_SD", "source": "35_P", "value": 1}, {"target": "22_M", "source": "21_STC", "value": 2}, {"target": "25_CHE", "source": "24_SU", "value": 1}, {"target": "18_DTA", "source": "17_SANiaR", "value": 35}, {"target": "4_FtLWiaS", "source": "3_CfP", "value": 107}, {"target": "19_WdIb", "source": "18_SaD", "value": 1}, {"target": "22_CHE", "source": "21_Bw", "value": 1}, {"target": "14_M", "source": "13_Wat", "value": 1}, {"target": "15_CM", "source": "14_Tas", "value": 1}, {"target": "2_FaN", "source": "1_RaS", "value": 148}, {"target": "5_TCaS", "source": "4_FtLWiaS", "value": 97}, {"target": "27_Dilih", "source": "26_FK", "value": 1}, {"target": "20_SAOFN", "source": "19_DTA", "value": 1}, {"target": "32_CR", "source": "31_VUTN", "value": 1}, {"target": "32_MaP", "source": "31_EBT", "value": 1}, {"target": "20_WdIb", "source": "19_SaD", "value": 1}, {"target": "33_BA", "source": "32_VUTN", "value": 1}, {"target": "12_SF", "source": "11_M", "value": 1}, {"target": "33_P", "source": "32_BA", "value": 1}, {"target": "4_SaD", "source": "3_Wat", "value": 1}, {"target": "13_Wat", "source": "12_FB", "value": 22}, {"target": "32_VUTN", "source": "31_EBT", "value": 1}, {"target": "17_M", "source": "16_SANiaR", "value": 2}, {"target": "12_Tas", "source": "11_Rasras", "value": 4}, {"target": "20_SANiaR", "source": "19_WdIb", "value": 1}, {"target": "36_VUTN", "source": "35_MtD", "value": 18}, {"target": "27_S", "source": "26_FK", "value": 1}, {"target": "36_Ml", "source": "35_M", "value": 1}, {"target": "14_SF", "source": "13_CM", "value": 3}, {"target": "13_FB", "source": "12_SF", "value": 3}, {"target": "7_RLNiA", "source": "6_TCaS", "value": 1}, {"target": "25_FK", "source": "24_SCM", "value": 12}, {"target": "30_BA", "source": "29_S", "value": 22}, {"target": "30_EBT", "source": "29_SD", "value": 2}, {"target": "19_CHE", "source": "18_Bw", "value": 12}, {"target": "15_SANiaR", "source": "14_WdIb", "value": 1}, {"target": "10_CtE", "source": "9_RLNiA", "value": 2}, {"target": "30_SD", "source": "29_MtD", "value": 1}, {"target": "16_SF", "source": "15_CM", "value": 1}, {"target": "24_FK", "source": "23_SAP", "value": 3}, {"target": "29_MtD", "source": "28_S", "value": 1}, {"target": "24_CHE", "source": "23_Bw", "value": 1}, {"target": "34_M", "source": "33_BA", "value": 1}, {"target": "22_SU", "source": "21_Bw", "value": 1}, {"target": "30_VUTN", "source": "29_MaP", "value": 1}, {"target": "17_Wat", "source": "16_FB", "value": 1}, {"target": "31_EBT", "source": "30_SD", "value": 1}, {"target": "32_BA", "source": "31_SCM", "value": 1}, {"target": "18_SAOFN", "source": "17_SANiaR", "value": 1}, {"target": "37_CR", "source": "36_MtD", "value": 1}, {"target": "5_FaN", "source": "4_SaD", "value": 1}, {"target": "14_Wat", "source": "13_FB", "value": 40}, {"target": "17_SANiaR", "source": "16_WdIb", "value": 37}, {"target": "30_Ml", "source": "29_M", "value": 4}, {"target": "31_MaP", "source": "30_EBT", "value": 2}, {"target": "22_SAOFN", "source": "21_CHE", "value": 2}, {"target": "21_CHE", "source": "20_SU", "value": 1}, {"target": "31_MtD", "source": "30_MaP", "value": 3}, {"target": "21_STC", "source": "20_CHE", "value": 3}, {"target": "5_FtLWiaS", "source": "4_CfP", "value": 1}, {"target": "35_P", "source": "34_VUTN", "value": 1}, {"target": "7_FtLWiaS", "source": "6_CfP", "value": 1}, {"target": "26_Dilih", "source": "25_FK", "value": 12}, {"target": "36_MtD", "source": "35_P", "value": 1}, {"target": "34_MaP", "source": "33_EBT", "value": 20}, {"target": "8_SAOFN", "source": "7_SANiaR", "value": 4}, {"target": "20_DTA", "source": "19_WdIb", "value": 1}, {"target": "21_CHE", "source": "20_Bw", "value": 1}, {"target": "23_Bw", "source": "22_Ml", "value": 1}, {"target": "29_M", "source": "28_BA", "value": 3}, {"target": "30_BA", "source": "29_Ml", "value": 1}, {"target": "6_CfP", "source": "5_FaN", "value": 1}, {"target": "25_SAP", "source": "24_SAOFN", "value": 25}, {"target": "17_Ml", "source": "16_WdIb", "value": 1}, {"target": "10_Tas", "source": "9_Rasras", "value": 3}, {"target": "27_Ml", "source": "26_M", "value": 1}, {"target": "29_S", "source": "28_Dilih", "value": 20}, {"target": "23_SAP", "source": "22_SAOFN", "value": 15}, {"target": "21_SU", "source": "20_Bw", "value": 29}, {"target": "28_EBT", "source": "27_SD", "value": 1}, {"target": "33_VUTN", "source": "32_MtD", "value": 1}, {"target": "25_Dilih", "source": "24_FK", "value": 3}, {"target": "25_SCM", "source": "24_STC", "value": 1}, {"target": "34_EBT", "source": "33_SD", "value": 1}, {"target": "27_SD", "source": "26_S", "value": 1}, {"target": "4_CfP", "source": "3_FaN", "value": 1}, {"target": "8_CtE", "source": "7_SANiaR", "value": 3}, {"target": "21_DTA", "source": "20_SANiaR", "value": 1}, {"target": "24_STC", "source": "23_SU", "value": 1}, {"target": "32_P", "source": "31_MtD", "value": 1}, {"target": "32_SD", "source": "31_P", "value": 21}, {"target": "25_SAP", "source": "24_STC", "value": 1}, {"target": "2_CfP", "source": "1_RaS", "value": 1}, {"target": "37_VUTN", "source": "36_MtD", "value": 1}, {"target": "20_Bw", "source": "19_STC", "value": 1}, {"target": "24_STC", "source": "23_CHE", "value": 1}, {"target": "19_WdIb", "source": "18_Dilih", "value": 1}, {"target": "18_SaD", "source": "17_Wat", "value": 1}, {"target": "3_FaN", "source": "2_RaS", "value": 1}, {"target": "16_SANiaR", "source": "15_WdIb", "value": 17}, {"target": "15_SaD", "source": "14_Wat", "value": 37}, {"target": "8_TCaS", "source": "7_MaP", "value": 1}, {"target": "12_FB", "source": "11_SF", "value": 22}, {"target": "13_CM", "source": "12_Tas", "value": 3}, {"target": "21_STC", "source": "20_WdIb", "value": 1}, {"target": "27_S", "source": "26_Dilih", "value": 11}, {"target": "18_Wat", "source": "17_FB", "value": 1}, {"target": "26_S", "source": "25_Dilih", "value": 1}, {"target": "29_MaP", "source": "28_SD", "value": 1}, {"target": "19_Ml", "source": "18_DTA", "value": 33}, {"target": "31_P", "source": "30_Ml", "value": 3}, {"target": "8_Rasras", "source": "7_RLNiA", "value": 1}, {"target": "8_TCaS", "source": "7_FtLWiaS", "value": 1}, {"target": "25_SU", "source": "24_CHE", "value": 1}, {"target": "28_Dilih", "source": "27_FK", "value": 22}, {"target": "17_DTA", "source": "16_SANiaR", "value": 15}, {"target": "3_Wat", "source": "2_FB", "value": 1}, {"target": "1_RaS", "source": "0_MB", "value": 174}, {"target": "28_SD", "source": "27_S", "value": 6}, {"target": "15_FB", "source": "14_SF", "value": 1}, {"target": "19_DTA", "source": "18_SANiaR", "value": 1}, {"target": "6_RLNiA", "source": "5_TCaS", "value": 92}, {"target": "38_P", "source": "37_Ml", "value": 1}, {"target": "1_CtE", "source": "0_MB", "value": 1}, {"target": "9_Rasras", "source": "8_CtE", "value": 3}, {"target": "35_MaP", "source": "34_EBT", "value": 1}, {"target": "29_Ml", "source": "28_M", "value": 1}, {"target": "21_Bw", "source": "20_Ml", "value": 1}, {"target": "32_VUTN", "source": "31_MaP", "value": 1}, {"target": "22_SAOFN", "source": "21_STC", "value": 13}, {"target": "19_STC", "source": "18_SU", "value": 1}, {"target": "31_MtD", "source": "30_BA", "value": 1}, {"target": "8_Rasras", "source": "7_CtE", "value": 79}, {"target": "27_S", "source": "26_SCM", "value": 1}, {"target": "23_STC", "source": "22_CHE", "value": 28}, {"target": "28_Ml", "source": "27_M", "value": 1}, {"target": "11_SF", "source": "10_CM", "value": 68}, {"target": "13_FB", "source": "12_M", "value": 39}, {"target": "14_Tas", "source": "13_Rasras", "value": 1}, {"target": "6_TCaS", "source": "5_FtLWiaS", "value": 1}, {"target": "31_VUTN", "source": "30_MaP", "value": 2}, {"target": "17_Bw", "source": "16_DTA", "value": 1}, {"target": "13_Rasras", "source": "12_CtE", "value": 1}, {"target": "2_RaS", "source": "1_CtE", "value": 1}, {"target": "15_M", "source": "14_SaD", "value": 1}, {"target": "26_FK", "source": "25_SU", "value": 1}, {"target": "18_STC", "source": "17_Bw", "value": 1}, {"target": "26_SCM", "source": "25_Dilih", "value": 1}, {"target": "32_P", "source": "31_Ml", "value": 1}, {"target": "32_MtD", "source": "31_MaP", "value": 1}, {"target": "9_RLNiA", "source": "8_TCaS", "value": 2}, {"target": "7_SANiaR", "source": "6_RLNiA", "value": 7}, {"target": "7_MaP", "source": "6_EBT", "value": 1}, {"target": "30_M", "source": "29_SD", "value": 1}, {"target": "16_FB", "source": "15_M", "value": 1}, {"target": "29_S", "source": "28_Ml", "value": 1}, {"target": "10_CM", "source": "9_Tas", "value": 69}, {"target": "38_P", "source": "37_BA", "value": 1}, {"target": "39_Nrp", "source": "38_IU", "value": 15}, {"target": "11_CM", "source": "10_Tas", "value": 2}, {"target": "15_SaD", "source": "14_M", "value": 1}, {"target": "9_Tas", "source": "8_Rasras", "value": 77}, {"target": "37_Ml", "source": "36_M", "value": 1}, {"target": "21_Bw", "source": "20_SAOFN", "value": 1}, {"target": "21_Bw", "source": "20_DTA", "value": 1}, {"target": "38_IU", "source": "37_CR", "value": 16}, {"target": "28_M", "source": "27_S", "value": 1}, {"target": "29_S", "source": "28_SCM", "value": 1}, {"target": "16_WdIb", "source": "15_M", "value": 2}, {"target": "12_CtE", "source": "11_MaP", "value": 1}, {"target": "11_Rasras", "source": "10_CtE", "value": 4}, {"target": "2_FB", "source": "1_RaS", "value": 1}, {"target": "34_Ml", "source": "33_M", "value": 1}, {"target": "20_Ml", "source": "19_DTA", "value": 1}, {"target": "18_SANiaR", "source": "17_Ml", "value": 1}, {"target": "16_DTA", "source": "15_SANiaR", "value": 1}, {"target": "35_MtD", "source": "34_MaP", "value": 19}, {"target": "15_Wat", "source": "14_WdIb", "value": 1}, {"target": "20_SU", "source": "19_SaD", "value": 1}, {"target": "17_SaD", "source": "16_Wat", "value": 1}, {"target": "16_SaD", "source": "15_Wat", "value": 1}, {"target": "22_Ml", "source": "21_DTA", "value": 1}, {"target": "31_SCM", "source": "30_Ml", "value": 1}, {"target": "33_M", "source": "32_VUTN", "value": 1}, {"target": "33_CR", "source": "32_VUTN", "value": 3}, {"target": "23_Ml", "source": "22_M", "value": 2}, {"target": "33_EBT", "source": "32_P", "value": 1}, {"target": "33_SD", "source": "32_P", "value": 1}, {"target": "31_P", "source": "30_BA", "value": 20}, {"target": "20_Bw", "source": "19_Ml", "value": 33}, {"target": "34_MaP", "source": "33_P", "value": 1}, {"target": "33_MtD", "source": "32_CR", "value": 1}, {"target": "17_SANiaR", "source": "16_SaD", "value": 1}, {"target": "36_M", "source": "35_BA", "value": 1}, {"target": "21_STC", "source": "20_SU", "value": 12}, {"target": "31_Ml", "source": "30_M", "value": 1}, {"target": "29_M", "source": "28_EBT", "value": 1}, {"target": "26_FK", "source": "25_SCM", "value": 1}, {"target": "18_Dilih", "source": "17_SaD", "value": 1}, {"target": "36_P", "source": "35_Ml", "value": 2}, {"target": "24_SU", "source": "23_Bw", "value": 1}, {"target": "22_DTA", "source": "21_STC", "value": 1}, {"target": "37_BA", "source": "36_Ml", "value": 1}, {"target": "16_WdIb", "source": "15_SaD", "value": 38}, {"target": "20_SU", "source": "19_CHE", "value": 12}, {"target": "16_SANiaR", "source": "15_SaD", "value": 1}, {"target": "15_WdIb", "source": "14_SaD", "value": 17}, {"target": "39_Nrp", "source": "38_P", "value": 2}, {"target": "17_DTA", "source": "16_WdIb", "value": 2}, {"target": "34_VUTN", "source": "33_MtD", "value": 1}, {"target": "33_Nrp", "source": "32_SD", "value": 1}, {"target": "24_SAOFN", "source": "23_Ml", "value": 2}, {"target": "19_DTA", "source": "18_SAOFN", "value": 1}, {"target": "22_CHE", "source": "21_SU", "value": 29}, {"target": "5_SD", "source": "4_FtLWiaS", "value": 1}, {"target": "18_DTA", "source": "17_M", "value": 2}, {"target": "10_SCM", "source": "9_SAP", "value": 2}, {"target": "34_M", "source": "33_VUTN", "value": 1}, {"target": "37_CR", "source": "36_P", "value": 2}, {"target": "6_EBT", "source": "5_SD", "value": 1}, {"target": "18_SU", "source": "17_DTA", "value": 1}, {"target": "35_Nrp", "source": "34_IU", "value": 1}, {"target": "37_CR", "source": "36_VUTN", "value": 14}, {"target": "28_SCM", "source": "27_Ml", "value": 1}, {"target": "35_BA", "source": "34_IU", "value": 1}, {"target": "32_CR", "source": "31_EBT", "value": 1}, {"target": "11_MaP", "source": "10_SCM", "value": 1}, {"target": "27_FK", "source": "26_SCM", "value": 22}, {"target": "15_M", "source": "14_SF", "value": 2}, {"target": "14_SaD", "source": "13_Wat", "value": 19}, {"target": "28_S", "source": "27_Dilih", "value": 1}, {"target": "12_SF", "source": "11_CM", "value": 2}, {"target": "14_WdIb", "source": "13_FB", "value": 1}, {"target": "23_CHE", "source": "22_SU", "value": 1}, {"target": "17_FB", "source": "16_SF", "value": 1}, {"target": "19_SU", "source": "18_Bw", "value": 3}, {"target": "26_M", "source": "25_Dilih", "value": 1}, {"target": "31_EBT", "source": "30_VUTN", "value": 1}, {"target": "24_SAOFN", "source": "23_STC", "value": 24}, {"target": "14_WdIb", "source": "13_Wat", "value": 2}, {"target": "30_MaP", "source": "29_EBT", "value": 5}, {"target": "33_EBT", "source": "32_SD", "value": 20}, {"target": "18_Bw", "source": "17_DTA", "value": 16}, {"target": "34_IU", "source": "33_CR", "value": 3}, {"target": "35_P", "source": "34_Ml", "value": 1}, {"target": "11_M", "source": "10_CM", "value": 1}, {"target": "19_SaD", "source": "18_Wat", "value": 1}, {"target": "12_M", "source": "11_SF", "value": 42}, {"target": "15_SaD", "source": "14_WdIb", "value": 1}, {"target": "33_IU", "source": "32_CR", "value": 1}, {"target": "23_SU", "source": "22_CHE", "value": 1}, {"target": "34_IU", "source": "33_MtD", "value": 1}, {"target": "38_CR", "source": "37_VUTN", "value": 1}, {"target": "3_CfP", "source": "2_FaN", "value": 113}, {"target": "9_SAP", "source": "8_SAOFN", "value": 4}, {"target": "35_M", "source": "34_IU", "value": 1}, {"target": "35_Ml", "source": "34_M", "value": 2}, {"target": "29_SD", "source": "28_BA", "value": 3}, {"target": "23_Bw", "source": "22_DTA", "value": 1}, {"target": "36_MtD", "source": "35_MaP", "value": 1}, {"target": "33_MtD", "source": "32_MaP", "value": 1}, {"target": "29_EBT", "source": "28_SD", "value": 5}, {"target": "39_IU", "source": "38_CR", "value": 1}], "nodes": [{"name": "26_M"}, {"name": "18_SU"}, {"name": "17_SaD"}, {"name": "18_SAOFN"}, {"name": "18_Dilih"}, {"name": "32_MtD"}, {"name": "11_MaP"}, {"name": "15_SaD"}, {"name": "14_M"}, {"name": "25_FK"}, {"name": "20_SAOFN"}, {"name": "22_SAOFN"}, {"name": "22_M"}, {"name": "32_BA"}, {"name": "18_STC"}, {"name": "25_CHE"}, {"name": "26_SCM"}, {"name": "20_Bw"}, {"name": "19_DTA"}, {"name": "37_VUTN"}, {"name": "17_DTA"}, {"name": "16_WdIb"}, {"name": "35_Ml"}, {"name": "28_M"}, {"name": "33_M"}, {"name": "24_STC"}, {"name": "19_WdIb"}, {"name": "36_P"}, {"name": "4_SaD"}, {"name": "22_DTA"}, {"name": "6_EBT"}, {"name": "22_SU"}, {"name": "34_IU"}, {"name": "8_SAOFN"}, {"name": "23_SAP"}, {"name": "17_FB"}, {"name": "33_CR"}, {"name": "20_WdIb"}, {"name": "30_BA"}, {"name": "31_MaP"}, {"name": "16_SANiaR"}, {"name": "33_VUTN"}, {"name": "30_EBT"}, {"name": "29_Ml"}, {"name": "20_DTA"}, {"name": "23_SU"}, {"name": "12_M"}, {"name": "5_FaN"}, {"name": "33_Nrp"}, {"name": "34_VUTN"}, {"name": "10_Tas"}, {"name": "30_VUTN"}, {"name": "39_Nrp"}, {"name": "1_CtE"}, {"name": "21_Bw"}, {"name": "23_Ml"}, {"name": "31_SCM"}, {"name": "36_Ml"}, {"name": "14_Wat"}, {"name": "39_IU"}, {"name": "31_P"}, {"name": "24_FK"}, {"name": "21_DTA"}, {"name": "16_SaD"}, {"name": "33_BA"}, {"name": "23_CHE"}, {"name": "3_FaN"}, {"name": "11_SF"}, {"name": "34_M"}, {"name": "32_CR"}, {"name": "30_Ml"}, {"name": "2_CfP"}, {"name": "26_FK"}, {"name": "21_CHE"}, {"name": "33_SD"}, {"name": "27_FK"}, {"name": "38_P"}, {"name": "37_BA"}, {"name": "31_MtD"}, {"name": "11_CM"}, {"name": "24_CHE"}, {"name": "36_MtD"}, {"name": "6_CfP"}, {"name": "35_BA"}, {"name": "33_EBT"}, {"name": "24_SAOFN"}, {"name": "4_FtLWiaS"}, {"name": "19_CHE"}, {"name": "9_RLNiA"}, {"name": "3_Wat"}, {"name": "2_FB"}, {"name": "20_Ml"}, {"name": "9_Tas"}, {"name": "29_MaP"}, {"name": "5_FtLWiaS"}, {"name": "35_Nrp"}, {"name": "26_S"}, {"name": "33_MtD"}, {"name": "16_Wat"}, {"name": "23_STC"}, {"name": "18_SANiaR"}, {"name": "19_STC"}, {"name": "31_VUTN"}, {"name": "18_Bw"}, {"name": "33_P"}, {"name": "16_FB"}, {"name": "17_Ml"}, {"name": "6_RLNiA"}, {"name": "28_S"}, {"name": "38_CR"}, {"name": "20_SANiaR"}, {"name": "28_EBT"}, {"name": "19_SU"}, {"name": "15_FB"}, {"name": "13_Rasras"}, {"name": "18_SaD"}, {"name": "8_CtE"}, {"name": "7_MaP"}, {"name": "19_SaD"}, {"name": "1_RaS"}, {"name": "15_Wat"}, {"name": "35_MtD"}, {"name": "25_Dilih"}, {"name": "5_SD"}, {"name": "7_RLNiA"}, {"name": "15_SANiaR"}, {"name": "25_SU"}, {"name": "34_EBT"}, {"name": "14_SF"}, {"name": "36_M"}, {"name": "26_Dilih"}, {"name": "12_FB"}, {"name": "28_SCM"}, {"name": "27_Dilih"}, {"name": "35_M"}, {"name": "14_WdIb"}, {"name": "20_SU"}, {"name": "17_SANiaR"}, {"name": "29_S"}, {"name": "2_RaS"}, {"name": "12_CtE"}, {"name": "6_TCaS"}, {"name": "18_DTA"}, {"name": "0_MB"}, {"name": "32_MaP"}, {"name": "34_MaP"}, {"name": "15_CM"}, {"name": "8_Rasras"}, {"name": "35_MaP"}, {"name": "24_SCM"}, {"name": "28_Ml"}, {"name": "30_SD"}, {"name": "27_Ml"}, {"name": "29_SD"}, {"name": "29_MtD"}, {"name": "27_SD"}, {"name": "7_CtE"}, {"name": "33_IU"}, {"name": "15_WdIb"}, {"name": "3_CfP"}, {"name": "8_TCaS"}, {"name": "28_SD"}, {"name": "17_Wat"}, {"name": "13_FB"}, {"name": "4_CfP"}, {"name": "29_EBT"}, {"name": "13_Wat"}, {"name": "17_M"}, {"name": "34_Ml"}, {"name": "13_CM"}, {"name": "17_Bw"}, {"name": "19_Ml"}, {"name": "24_SU"}, {"name": "31_EBT"}, {"name": "_"}, {"name": "9_Rasras"}, {"name": "28_BA"}, {"name": "32_SD"}, {"name": "7_FtLWiaS"}, {"name": "21_SU"}, {"name": "11_M"}, {"name": "27_S"}, {"name": "15_M"}, {"name": "10_SCM"}, {"name": "14_Tas"}, {"name": "5_TCaS"}, {"name": "32_P"}, {"name": "25_SAP"}, {"name": "22_CHE"}, {"name": "10_CM"}, {"name": "14_SaD"}, {"name": "36_VUTN"}, {"name": "32_VUTN"}, {"name": "23_Bw"}, {"name": "27_M"}, {"name": "16_DTA"}, {"name": "35_P"}, {"name": "38_IU"}, {"name": "22_Ml"}, {"name": "30_MaP"}, {"name": "37_Ml"}, {"name": "30_M"}, {"name": "28_Dilih"}, {"name": "12_SF"}, {"name": "25_SCM"}, {"name": "12_Tas"}, {"name": "36_SD"}, {"name": "21_STC"}, {"name": "18_Wat"}, {"name": "29_M"}, {"name": "16_SF"}, {"name": "31_Ml"}, {"name": "10_CtE"}, {"name": "7_SANiaR"}, {"name": "11_Rasras"}, {"name": "9_SAP"}, {"name": "20_CHE"}, {"name": "2_FaN"}, {"name": "37_CR"}]}
<!DOCTYPE html>
<meta charset="utf-8">
<title>SANKEY Experiment</title>
<style>
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
.link:hover {
stroke-opacity: .5;
}
</style>
<body>
<p id="chart">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.12/d3.js"></script>
<script src="sankey.js"></script>
<script>
var units = "Widgets";
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 12000 - margin.left - margin.right,
height = 940 - margin.top - margin.bottom;
//width = 1200 - margin.left - margin.right,
//height = 740 - margin.top - margin.bottom;
var formatNumber = d3.format(",.0f"), // zero decimal places
format = function(d) { return formatNumber(d) + " " + units; },
color = d3.scale.category20();
// append the svg canvas to the page
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Set the sankey diagram properties
var sankey = d3.sankey()
.nodeWidth(36)
.nodePadding(10)
.size([width, height]);
var path = sankey.link();
// load the data
d3.json("camperpath.json", function(error, graph) {
var nodeMap = {};
graph.nodes.forEach(function(x) { nodeMap[x.name] = x; });
graph.links = graph.links.map(function(x) {
return {
source: nodeMap[x.source],
target: nodeMap[x.target],
value: x.value
};
});
sankey
.nodes(graph.nodes)
.links(graph.links)
.layout(32);
// add in the links
var link = svg.append("g").selectAll(".link")
.data(graph.links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.sort(function(a, b) { return b.dy - a.dy; });
// add the link titles
link.append("title")
.text(function(d) {
return d.source.name + " → " +
d.target.name + "\n" + format(d.value); });
// add in the nodes
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function() {
this.parentNode.appendChild(this); })
.on("drag", dragmove));
// add the rectangles for the nodes
node.append("rect")
.attr("height", function(d) { return d.dy; })
.attr("width", sankey.nodeWidth())
.style("fill", function(d) {
return d.color = color(d.name.replace(/ .*/, "")); })
.style("stroke", function(d) {
return d3.rgb(d.color).darker(2); })
.append("title")
.text(function(d) {
return d.name + "\n" + format(d.value); });
// add in the title for the nodes
node.append("text")
.attr("x", -6)
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function(d) { return d.name; })
.filter(function(d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start");
// the function for moving the nodes
function dragmove(d) {
d3.select(this).attr("transform",
"translate(" + (
d.x = Math.max(0, Math.min(width - d.dx, d3.event.x))
) + "," + (
d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))
) + ")");
sankey.relayout();
link.attr("d", path);
}
});
</script>
</body>
</html>
d3.sankey = function() {
var sankey = {},
nodeWidth = 24,
nodePadding = 8,
size = [1, 1],
nodes = [],
links = [],
sinksRight = true;
sankey.nodeWidth = function(_) {
if (!arguments.length) return nodeWidth;
nodeWidth = +_;
return sankey;
};
sankey.nodePadding = function(_) {
if (!arguments.length) return nodePadding;
nodePadding = +_;
return sankey;
};
sankey.nodes = function(_) {
if (!arguments.length) return nodes;
nodes = _;
return sankey;
};
sankey.links = function(_) {
if (!arguments.length) return links;
links = _;
return sankey;
};
sankey.size = function(_) {
if (!arguments.length) return size;
size = _;
return sankey;
};
sankey.sinksRight = function (_) {
if (!arguments.length) return sinksRight;
sinksRight = _;
return sankey;
};
sankey.layout = function(iterations) {
computeNodeLinks();
computeNodeValues();
computeNodeBreadths();
computeNodeDepths(iterations);
return sankey;
};
sankey.relayout = function() {
computeLinkDepths();
return sankey;
};
// SVG path data generator, to be used as "d" attribute on "path" element selection.
sankey.link = function() {
var curvature = .5;
function link(d) {
var x0 = d.source.x + d.source.dx,
x1 = d.target.x,
xi = d3.interpolateNumber(x0, x1),
x2 = xi(curvature),
x3 = xi(1 - curvature),
y0 = d.source.y + d.sy + d.dy / 2,
y1 = d.target.y + d.ty + d.dy / 2;
return "M" + x0 + "," + y0
+ "C" + x2 + "," + y0
+ " " + x3 + "," + y1
+ " " + x1 + "," + y1;
}
link.curvature = function(_) {
if (!arguments.length) return curvature;
curvature = +_;
return link;
};
return link;
};
// Populate the sourceLinks and targetLinks for each node.
// Also, if the source and target are not objects, assume they are indices.
function computeNodeLinks() {
nodes.forEach(function(node) {
// Links that have this node as source.
node.sourceLinks = [];
// Links that have this node as target.
node.targetLinks = [];
});
links.forEach(function(link) {
var source = link.source,
target = link.target;
if (typeof source === "number") source = link.source = nodes[link.source];
if (typeof target === "number") target = link.target = nodes[link.target];
source.sourceLinks.push(link);
target.targetLinks.push(link);
});
}
// Compute the value (size) of each node by summing the associated links.
function computeNodeValues() {
nodes.forEach(function(node) {
node.value = Math.max(
d3.sum(node.sourceLinks, value),
d3.sum(node.targetLinks, value)
);
});
}
// Iteratively assign the breadth (x-position) for each node.
// Nodes are assigned the maximum breadth of incoming neighbors plus one;
// nodes with no incoming links are assigned breadth zero, while
// nodes with no outgoing links are assigned the maximum breadth.
function computeNodeBreadths() {
var remainingNodes = nodes,
nextNodes,
x = 0;
// Work from left to right.
// Keep updating the breath (x-position) of nodes that are target of recently updated nodes.
while (remainingNodes.length && x < nodes.length) {
nextNodes = [];
remainingNodes.forEach(function(node) {
node.x = x;
node.dx = nodeWidth;
node.sourceLinks.forEach(function(link) {
if (nextNodes.indexOf(link.target) < 0) {
nextNodes.push(link.target);
}
});
});
remainingNodes = nextNodes;
++x;
}
// Optionally move pure sinks always to the right.
if (sinksRight) {
moveSinksRight(x);
}
scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));
}
function moveSourcesRight() {
nodes.forEach(function(node) {
if (!node.targetLinks.length) {
node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;
}
});
}
function moveSinksRight(x) {
nodes.forEach(function(node) {
if (!node.sourceLinks.length) {
node.x = x - 1;
}
});
}
function scaleNodeBreadths(kx) {
nodes.forEach(function(node) {
node.x *= kx;
});
}
// Compute the depth (y-position) for each node.
function computeNodeDepths(iterations) {
// Group nodes by breath.
var nodesByBreadth = d3.nest()
.key(function(d) { return d.x; })
.sortKeys(d3.ascending)
.entries(nodes)
.map(function(d) { return d.values; });
//
initializeNodeDepth();
resolveCollisions();
computeLinkDepths();
for (var alpha = 1; iterations > 0; --iterations) {
relaxRightToLeft(alpha *= .99);
resolveCollisions();
computeLinkDepths();
relaxLeftToRight(alpha);
resolveCollisions();
computeLinkDepths();
}
function initializeNodeDepth() {
// Calculate vertical scaling factor.
var ky = d3.min(nodesByBreadth, function(nodes) {
return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);
});
nodesByBreadth.forEach(function(nodes) {
nodes.forEach(function(node, i) {
node.y = i;
node.dy = node.value * ky;
});
});
links.forEach(function(link) {
link.dy = link.value * ky;
});
}
function relaxLeftToRight(alpha) {
nodesByBreadth.forEach(function(nodes, breadth) {
nodes.forEach(function(node) {
if (node.targetLinks.length) {
// Value-weighted average of the y-position of source node centers linked to this node.
var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);
node.y += (y - center(node)) * alpha;
}
});
});
function weightedSource(link) {
return (link.source.y + link.sy + link.dy / 2) * link.value;
}
}
function relaxRightToLeft(alpha) {
nodesByBreadth.slice().reverse().forEach(function(nodes) {
nodes.forEach(function(node) {
if (node.sourceLinks.length) {
// Value-weighted average of the y-positions of target nodes linked to this node.
var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);
node.y += (y - center(node)) * alpha;
}
});
});
function weightedTarget(link) {
return (link.target.y + link.ty + link.dy / 2) * link.value;
}
}
function resolveCollisions() {
nodesByBreadth.forEach(function(nodes) {
var node,
dy,
y0 = 0,
n = nodes.length,
i;
// Push any overlapping nodes down.
nodes.sort(ascendingDepth);
for (i = 0; i < n; ++i) {
node = nodes[i];
dy = y0 - node.y;
if (dy > 0) node.y += dy;
y0 = node.y + node.dy + nodePadding;
}
// If the bottommost node goes outside the bounds, push it back up.
dy = y0 - nodePadding - size[1];
if (dy > 0) {
y0 = node.y -= dy;
// Push any overlapping nodes back up.
for (i = n - 2; i >= 0; --i) {
node = nodes[i];
dy = node.y + node.dy + nodePadding - y0;
if (dy > 0) node.y -= dy;
y0 = node.y;
}
}
});
}
function ascendingDepth(a, b) {
return a.y - b.y;
}
}
// Compute y-offset of the source endpoint (sy) and target endpoints (ty) of links,
// relative to the source/target node's y-position.
function computeLinkDepths() {
nodes.forEach(function(node) {
node.sourceLinks.sort(ascendingTargetDepth);
node.targetLinks.sort(ascendingSourceDepth);
});
nodes.forEach(function(node) {
var sy = 0, ty = 0;
node.sourceLinks.forEach(function(link) {
link.sy = sy;
sy += link.dy;
});
node.targetLinks.forEach(function(link) {
link.ty = ty;
ty += link.dy;
});
});
function ascendingSourceDepth(a, b) {
return a.source.y - b.source.y;
}
function ascendingTargetDepth(a, b) {
return a.target.y - b.target.y;
}
}
// Y-position of the middle of a node.
function center(node) {
return node.y + node.dy / 2;
}
// Value property accessor.
function value(x) {
return x.value;
}
return sankey;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment