├── .nojekyll ├── libraries ├── frameworks │ └── bootstrap │ │ ├── js │ │ ├── main.js │ │ ├── plugins.js │ │ └── vendor │ │ │ ├── modernizr-2.6.1-respond-1.1.0.min.js │ │ │ └── bootstrap.min.js │ │ ├── robots.txt │ │ ├── layouts │ │ ├── slide.html │ │ ├── hero.html │ │ ├── special.html │ │ ├── hero2.html │ │ ├── div.html │ │ ├── scripts.html │ │ └── deck.html │ │ ├── ico │ │ ├── apple-touch-icon.png │ │ ├── apple-touch-icon-precomposed.png │ │ ├── apple-touch-icon-57x57-precomposed.png │ │ ├── apple-touch-icon-72x72-precomposed.png │ │ ├── apple-touch-icon-114x114-precomposed.png │ │ └── apple-touch-icon-144x144-precomposed.png │ │ ├── img │ │ ├── glyphicons-halflings.png │ │ └── glyphicons-halflings-white.png │ │ ├── humans.txt │ │ ├── css │ │ ├── main.css │ │ └── bootstrap-responsive.min.css │ │ ├── partials │ │ ├── footer.html │ │ ├── navbar.html │ │ └── head.html │ │ ├── 404.html │ │ └── index.html ├── widgets │ └── d3_sankey │ │ ├── config.yml │ │ ├── css │ │ └── sankey.css │ │ ├── js │ │ ├── LICENSE-d3.md │ │ └── sankey.js │ │ └── layouts │ │ └── chart.html └── highlighters │ └── prettify │ ├── prettify.html │ ├── css │ ├── twitter-bootstrap.css │ ├── desert.css │ ├── default.css │ ├── sons-of-obsidian.css │ ├── sunburst.css │ ├── hemisu-light.css │ └── tomorrow-night-bright.css │ └── js │ └── lang-r.js ├── holdings.txt ├── example_pimco.png ├── PIMCO Bond Stats.xls ├── figure ├── unnamed-chunk-2.png └── unnamed-chunk-3.png ├── assets └── fig │ ├── unnamed-chunk-3.png │ └── unnamed-chunk-5.png ├── config.yml ├── .gitattributes ├── css └── sankey.css ├── wastedfood.txt ├── example_pimco.R ├── example_rcharts_gallery.R ├── example_hirst_horse.R ├── js ├── LICENSE-d3.md └── sankey.js ├── example_hirst_f1.R ├── example_hirst_f1_2.R ├── example_pimco.Rmd ├── example_pimco.md ├── example_random_network.R ├── .gitignore ├── layouts ├── chart.html └── chart_static_title.html ├── example_build_network_sankey.Rmd ├── example.R ├── example_build_network_sankey.md └── example_build_network_sankey.html /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/js/main.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /holdings.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/holdings.txt -------------------------------------------------------------------------------- /example_pimco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/example_pimco.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/layouts/slide.html: -------------------------------------------------------------------------------- 1 | {{{ slide.header }}} 2 | {{{ slide.content }}} 3 | -------------------------------------------------------------------------------- /PIMCO Bond Stats.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/PIMCO Bond Stats.xls -------------------------------------------------------------------------------- /figure/unnamed-chunk-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/figure/unnamed-chunk-2.png -------------------------------------------------------------------------------- /figure/unnamed-chunk-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/figure/unnamed-chunk-3.png -------------------------------------------------------------------------------- /assets/fig/unnamed-chunk-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/assets/fig/unnamed-chunk-3.png -------------------------------------------------------------------------------- /assets/fig/unnamed-chunk-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/assets/fig/unnamed-chunk-5.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/ico/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/libraries/frameworks/bootstrap/ico/apple-touch-icon.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/libraries/frameworks/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/ico/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/libraries/frameworks/bootstrap/ico/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timelyportfolio/rCharts_d3_sankey/HEAD/libraries/frameworks/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/layouts/hero.html: -------------------------------------------------------------------------------- 1 |
Styled using Bootstrap. Hosted on GitHub. Icons from Font-Awesome. Web fonts from Google. Generated by Slidify
2 | -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/layouts/div.html: -------------------------------------------------------------------------------- 1 |code24 | * 25 | * Language definition from 26 | * http://cran.r-project.org/doc/manuals/R-lang.html. 27 | * Many of the regexes are shared with the pygments SLexer, 28 | * http://pygments.org/. 29 | * 30 | * @author jeffrey.arnold@gmail.com 31 | */ 32 | PR['registerLangHandler']( 33 | PR['createSimpleLexer']( 34 | [ 35 | [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 36 | [PR['PR_STRING'], /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'], 37 | [PR['PR_STRING'], /^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/, null, "'"] 38 | ], 39 | [ 40 | [PR['PR_COMMENT'], /^#.*/], 41 | [PR['PR_KEYWORD'], /^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![A-Za-z0-9_.])/], 42 | // hex numbes 43 | [PR['PR_LITERAL'], /^0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?/], 44 | // Decimal numbers 45 | [PR['PR_LITERAL'], /^[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?[Li]?/], 46 | // builtin symbols 47 | [PR['PR_LITERAL'], /^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|[0-9]+))(?![A-Za-z0-9_.])/], 48 | // assignment, operators, and parens, etc. 49 | [PR['PR_PUNCTUATION'], /^(?:<-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\*|\+|\^|\/|!|%.*?%|=|~|\$|@|:{1,3}|[\[\](){};,?])/], 50 | // valid variable names 51 | [PR['PR_PLAIN'], /^(?:[A-Za-z]+[A-Za-z0-9_.]*|\.[a-zA-Z_][0-9a-zA-Z\._]*)(?![A-Za-z0-9_.])/], 52 | // string backtick 53 | [PR['PR_STRING'], /^`.+`/] 54 | ]), 55 | ['r', 's', 'R', 'S', 'Splus']); 56 | -------------------------------------------------------------------------------- /libraries/highlighters/prettify/css/hemisu-light.css: -------------------------------------------------------------------------------- 1 | /* Hemisu Light */ 2 | /* Original theme - http://noahfrederick.com/vim-color-scheme-hemisu/ */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #111111; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #739200; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #739200; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #999999; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #ff0055; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #538192; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #111111; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #111111; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #111111; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #111111; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #739200; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #ff0055; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #111111; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #111111; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #538192; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | pre.prettyprint { 99 | background: white; 100 | font-family: Menlo, Monaco, Consolas, monospace; 101 | /* font-size: 12px;*/ 102 | line-height: 1.5; 103 | border: 1px solid #ccc; 104 | padding: 10px; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; } 111 | 112 | /* IE indents via margin-left */ 113 | li.L0, 114 | li.L1, 115 | li.L2, 116 | li.L3, 117 | li.L4, 118 | li.L5, 119 | li.L6, 120 | li.L7, 121 | li.L8, 122 | li.L9 { 123 | /* */ } 124 | 125 | /* Alternate shading for lines */ 126 | li.L1, 127 | li.L3, 128 | li.L5, 129 | li.L7, 130 | li.L9 { 131 | /* */ } -------------------------------------------------------------------------------- /libraries/highlighters/prettify/css/tomorrow-night-bright.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Blue Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #eaeaea; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: #b9ca4a; } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: #c397d8; } 17 | 18 | /* a comment */ 19 | .com { 20 | color: #969896; } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: #7aa6da; } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: #e78c45; } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #eaeaea; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #eaeaea; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #eaeaea; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #d54e53; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #e78c45; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #70c0b1; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #e78c45; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #d54e53; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #7aa6da; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | pre.prettyprint { 99 | background: black; 100 | font-family: Menlo, Monaco, Consolas, monospace; 101 | font-size: 12px; 102 | line-height: 1.5; 103 | border: 1px solid #ccc; 104 | padding: 10px; } 105 | 106 | /* Specify class=linenums on a pre to get line numbering */ 107 | ol.linenums { 108 | margin-top: 0; 109 | margin-bottom: 0; } 110 | 111 | /* IE indents via margin-left */ 112 | li.L0, 113 | li.L1, 114 | li.L2, 115 | li.L3, 116 | li.L4, 117 | li.L5, 118 | li.L6, 119 | li.L7, 120 | li.L8, 121 | li.L9 { 122 | /* */ } 123 | 124 | /* Alternate shading for lines */ 125 | li.L1, 126 | li.L3, 127 | li.L5, 128 | li.L7, 129 | li.L9 { 130 | /* */ } -------------------------------------------------------------------------------- /example_random_network.R: -------------------------------------------------------------------------------- 1 | #walk through the steps of creating a tree network for a sankey 2 | #and assigning random weights to the base vertices(out degree = 1) 3 | #and then summing so each edge weight is properly defined 4 | #great exercise to learn the construction of a sankey 5 | #and the conditions for a network to be drawn properly by sankey 6 | 7 | #then plot our network with the rCharts implementation of d3.js sankey plugin 8 | 9 | require(igraph) 10 | require(rCharts) 11 | 12 | 13 | g2 <- graph.tree(40,children=4) 14 | #to construct a sankey the weight of each vertex should be the sum 15 | #of its outgoing edges 16 | #I believe the first step in creating a network that satisfies this condition 17 | #is define a vertex weight for all vertexes with out degree = 0 18 | #but first let's define 0 for all 19 | V(g2)$weight = 0 20 | #now for all vertexes with out degree = 0 21 | V(g2)[degree(g2,mode="out")==0]$weight <- runif(n=length(V(g2)[degree(g2,mode="out")==0]),min=0,max=100) 22 | #the lowest level of the heirarchy is defined with a random weight 23 | #with the lowest level defined we should now be able to sum the vertex weights 24 | #to define the edge weight 25 | #E(g2)$weight = 0.1 #define all weights small to visually see as we build sankey 26 | E(g2)[to(V(g2)$weight>0)]$weight <- V(g2)[V(g2)$weight>0]$weight 27 | #and to find the neighbors to the 0 out degree vertex 28 | #we could do V(g2)[nei(degree(g2,mode="out")==0)] 29 | #we have everything we need to build the rest by summing 30 | #these edge weights if there are edges still undefined 31 | #so set up a loop to run until all edges have a defined weight 32 | while(max(is.na(E(g2)$weight))) { 33 | #get.data.frame gives us from, to, and weight 34 | #we will get this to make an easier reference later 35 | df <- get.data.frame(g2) 36 | #now go through each edge and find the sum of all its subedges 37 | #we need to check to make sure out degree of its "to" vertex is not 0 38 | #or we will get 0 since there are no edges for vertex with out degree 0 39 | for (i in 1:nrow(df)) { 40 | x = df[i,] 41 | #sum only those with out degree > 0 or sum will be 0 42 | if(max(df$from==x$to)) { 43 | E(g2)[from(x$from) & to(x$to)]$weight = sum(E(g2)[from(x$to)]$weight) 44 | } 45 | } 46 | } 47 | 48 | 49 | #just a quick check on the adjacency 50 | get.adjacency(g2,sparse = FALSE,attr="weight") 51 | 52 | 53 | 54 | 55 | #E(g2)$weight <- runif(length(E(g2))) 56 | edgelistWeight <- get.data.frame(g2) 57 | colnames(edgelistWeight) <- c("source","target","value") 58 | edgelistWeight$source <- as.character(edgelistWeight$source) 59 | edgelistWeight$target <- as.character(edgelistWeight$target) 60 | 61 | sankeyPlot2 <- rCharts$new() 62 | sankeyPlot2$setLib('.') 63 | sankeyPlot2$setTemplate(script = "layouts/chart.html") 64 | 65 | sankeyPlot2$set( 66 | data = edgelistWeight, 67 | nodeWidth = 15, 68 | nodePadding = 10, 69 | layout = 32, 70 | width = 960, 71 | height = 500 72 | ) 73 | 74 | sankeyPlot2 75 | 76 | 77 | #now for fun, let's plot the network with igraph 78 | plot(g2) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /layouts/chart.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 123 | -------------------------------------------------------------------------------- /libraries/widgets/d3_sankey/layouts/chart.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 123 | -------------------------------------------------------------------------------- /layouts/chart_static_title.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 126 | -------------------------------------------------------------------------------- /libraries/frameworks/bootstrap/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
Sorry, but the page you were trying to view does not exist.
146 |It looks like this was the result of either:
147 |This is a template for a simple marketing or informational website. It includes a large callout called the hero unit and three supporting pieces of content. Use it as a starting point to create something more unique.
75 | 76 |Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.
83 | 84 |Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.
88 | 89 |Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
93 | 94 |
40 |
41 | ```{r echo=F, warning= F, message=F}
42 | opts_chunk$set(
43 | message = FALSE,
44 | warning = FALSE,
45 | error = FALSE,
46 | tidy = FALSE,
47 | cache = FALSE,
48 | results = 'asis'
49 | )
50 | ```
51 | # Sankey from Scratch using `rCharts`, `d3.js`, and `igraph`
52 |
53 | ## Introduction
54 |
55 | This example will walk through the steps of using the `R` package [`igraph`](http://igraph.sourceforge.net/) to create a tree network for a [sankey diagram](http://econ.st/JwNX8s). This is a great exercise to learn some basics of `igraph`, explore the construction of a sankey, and determine the conditions for a network to be drawn properly as a sankey. After all of this, we will plot our network with the [`rCharts`](http://rcharts.io/site) implementation of the [d3.js sankey plugin](https://github.com/d3/d3-plugins/blob/master/sankey/sankey.js).
56 |
57 |
58 | ## Build a Network
59 | Let's first start by loading the `igraph` and `rCharts` packages. Then we will use `graph.tree` to build a tree network with 40 vertices with 4 children.
60 | ```{r}
61 | require(igraph)
62 | require(rCharts)
63 |
64 | g <- graph.tree(40, children = 4)
65 | ```
66 | For fun, we will assign a weight of 1 `E(g)$weight = 1` for each edge and then draw a Sankey diagram using `rCharts`. Going forward I will try to explain the `R` code through comments in the code block.
67 |
68 | ## Plot Our Sankey to Find a Problem
69 | ```{r}
70 | E(g)$weight = 1
71 |
72 | edgelist <- get.data.frame(g) #this will give us a data frame with from,to,weight
73 | colnames(edgelist) <- c("source","target","value")
74 | #make character rather than numeric for proper functioning
75 | edgelist$source <- as.character(edgelist$source)
76 | edgelist$target <- as.character(edgelist$target)
77 |
78 | sankeyPlot <- rCharts$new()
79 | sankeyPlot$setLib('libraries/widgets/d3_sankey')
80 | sankeyPlot$setTemplate(script = "libraries/widgets/d3_sankey/layouts/chart.html")
81 |
82 | sankeyPlot$set(
83 | data = edgelist,
84 | nodeWidth = 15,
85 | nodePadding = 10,
86 | layout = 32,
87 | width = 960,
88 | height = 500
89 | )
90 |
91 | sankeyPlot$print(chartId = 'sankey1')
92 | ```
93 |
94 | Interact with the sankey plot a little, and try to find the problem in our hastily constructed network. Hovering over the vertex 4 will reveal our issue. The edge from 1 to 4 is not as big as the sum of the edges going out from 4. For this to make sense, unless 4 is magically creating something, the sum of the inflow should equal the sum of the outflow. Since 4 has four children each with weight of 1 (outflow = 1 + 1 + 1 + 1 = 4), we would expect the inflow to also be 4. It is only 1 though since we made all our edges' weights = 1 `E(g)$weight = 1`. How then would we build our network with edge weights so that for each vertex, the sum of in equals the sum of out.
95 |
96 |
97 | ## Fix Our Problem For a Beautiful Sankey
98 | I am a network novice, so while the code below works, I am sure there are better ways of accomplishing the desired result. I heavily commented the code, but I will quickly describe the steps. The code starts at the lowest level of the heirarchy, or those vertexes where there is nothing going out (out degree = 0). In our network, these are 11 through 40. With `igraph` we can identify these by `V(g2)[degree(g2,mode="out")==0]`. For these we will assign a weight. Then we will loop through all of the edges summing all of the weights of the out until we have reached the top of the heirarchy.
99 |
100 | ```{r}
101 | g2 <- graph.tree(40, children=4)
102 | #to construct a sankey the weight of each vertex should be the sum
103 | #of its outgoing edges
104 | #I believe the first step in creating a network that satisfies this condition
105 | #is define a vertex weight for all vertexes with out degree = 0
106 | #but first let's define 0 for all
107 | V(g2)$weight = 0
108 | #now for all vertexes with out degree = 0
109 | V(g2)[degree(g2,mode="out")==0]$weight <- runif(n=length(V(g2)[degree(g2,mode="out")==0]),min=0,max=100)
110 | #the lowest level of the heirarchy is defined with a random weight
111 | #with the lowest level defined we should now be able to sum the vertex weights
112 | #to define the edge weight
113 | #E(g2)$weight = 0.1 #define all weights small to visually see as we build sankey
114 | E(g2)[to(V(g2)$weight>0)]$weight <- V(g2)[V(g2)$weight>0]$weight
115 | #and to find the neighbors to the 0 out degree vertex
116 | #we could do V(g2)[nei(degree(g2,mode="out")==0)]
117 | #we have everything we need to build the rest by summing
118 | #these edge weights if there are edges still undefined
119 | #so set up a loop to run until all edges have a defined weight
120 | while(max(is.na(E(g2)$weight))) {
121 | #get.data.frame gives us from, to, and weight
122 | #we will get this to make an easier reference later
123 | df <- get.data.frame(g2)
124 | #now go through each edge and find the sum of all its subedges
125 | #we need to check to make sure out degree of its "to" vertex is not 0
126 | #or we will get 0 since there are no edges for vertex with out degree 0
127 | for (i in 1:nrow(df)) {
128 | x = df[i,]
129 | #sum only those with out degree > 0 or sum will be 0
130 | if(max(df$from==x$to)) {
131 | E(g2)[from(x$from) & to(x$to)]$weight = sum(E(g2)[from(x$to)]$weight)
132 | }
133 | }
134 | }
135 |
136 | edgelistWeight <- get.data.frame(g2)
137 | colnames(edgelistWeight) <- c("source","target","value")
138 | edgelistWeight$source <- as.character(edgelistWeight$source)
139 | edgelistWeight$target <- as.character(edgelistWeight$target)
140 |
141 | sankeyPlot2 <- rCharts$new()
142 | sankeyPlot2$setLib('libraries/widgets/d3_sankey')
143 | sankeyPlot2$setTemplate(script = 'libraries/widgets/d3_sankey/layouts/chart.html')
144 |
145 | sankeyPlot2$set(
146 | data = edgelistWeight,
147 | nodeWidth = 15,
148 | nodePadding = 10,
149 | layout = 32,
150 | width = 960,
151 | height = 500
152 | )
153 |
154 | sankeyPlot2
155 | ```
156 |
157 | ## Another Look at Our Network
158 | There are very [good examples](http://rulesofreason.wordpress.com/tag/plot-igraph/) illustrating the use of `igraph` to plot a network. This is not one of these examples. For fun though, let's plot the network with igraph using just the defaults to compare it to our Sankey output from above.
159 |
160 | ```{r}
161 | plot(g2)
162 | ```
163 |
164 | ## Lots More Sankey
165 | Believe it or not, there is an entire site devoted to sankey diagrams. For all the sankey you can handle, check out http://sankey-diagrams.com. Here are a couple more sankeys generated from `rCharts`: http://rcharts.io/viewer/?6001601#.UeWfuY3VCSo, http://rcharts.io/viewer/?6003605, http://rcharts.io/viewer/?6003575.
--------------------------------------------------------------------------------
/example.R:
--------------------------------------------------------------------------------
1 | require(rCharts)
2 | require(rjson)
3 | require(igraph)
4 |
5 | #get source from original example
6 | #this is a JSON, so will need to translate
7 | #this is complicated and unnecessary but feel I need to replicate
8 | #for completeness
9 |
10 | #expect most data to come straight from R
11 | #in form of source, target, value
12 |
13 | links <- matrix(unlist(
14 | rjson::fromJSON(
15 | file = "http://bost.ocks.org/mike/sankey/energy.json"
16 | )$links
17 | ),ncol = 3, byrow = TRUE)
18 |
19 | nodes <- unlist(
20 | rjson::fromJSON(
21 | file = "http://bost.ocks.org/mike/sankey/energy.json"
22 | )$nodes
23 | )
24 |
25 | #convert to data.frame so souce and target can be character and value numeric
26 | links <- data.frame(links)
27 | colnames(links) <- c("source", "target", "value")
28 | links$source <- sapply(links$source, FUN = function(x) {return(as.character(nodes[x+1]))}) #x+1 since js starts at 0
29 | links$target <- sapply(links$target, FUN = function(x) {return(nodes[x+1])}) #x+1 since js starts at 0
30 |
31 |
32 | #now we finally have the data in the form we need
33 | sankeyPlot <- rCharts$new()
34 | sankeyPlot$setLib('.')
35 | sankeyPlot$setTemplate(script = "layouts/chart.html")
36 |
37 | sankeyPlot$set(
38 | data = links,
39 | nodeWidth = 15,
40 | nodePadding = 10,
41 | layout = 32,
42 | width = 960,
43 | height = 500,
44 | units = "TWh",
45 | title = "Sankey Diagram"
46 | )
47 |
48 | sankeyPlot
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | data(foodwebs, package = "igraphdata")
71 | data(karate, package = "igraphdata")
72 | data(Koenigsberg, package = "igraphdata")
73 | edgelist <- get.data.frame(foodwebs$ChesLower)
74 |
75 | #simulate a network
76 | g <- graph.tree(26,children=2)
77 | edgelist <- get.data.frame(g)
78 | edgelist$value <- 1
79 | colnames(edgelist) <- c("source","target","value")
80 | edgelist$source <- LETTERS[edgelist$source]
81 | edgelist$target <- LETTERS[edgelist$target]
82 |
83 | sankeyPlot <- rCharts$new()
84 | sankeyPlot$setLib('.')
85 | sankeyPlot$setTemplate(script = "layouts/chart.html")
86 |
87 | sankeyPlot$set(
88 | data = edgelist,
89 | nodeWidth = 15,
90 | nodePadding = 10,
91 | layout = 32,
92 | width = 960,
93 | height = 500
94 | )
95 |
96 | sankeyPlot
97 |
98 |
99 | g2 <- graph.tree(40,children=4)
100 | #to construct a sankey the weight of each vertex should be the sum
101 | #of its outgoing edges
102 | #I believe the first step in creating a network that satisfies this condition
103 | #is define a vertex weight for all vertexes with out degree = 0
104 | #but first let's define 0 for all
105 | V(g2)$weight = 0
106 | #now for all vertexes with out degree = 0
107 | V(g2)[degree(g2,mode="out")==0]$weight <- runif(n=length(V(g2)[degree(g2,mode="out")==0]),min=0,max=100)
108 | #the lowest level of the heirarchy is defined with a random weight
109 | #with the lowest level defined we should now be able to sum the vertex weights
110 | #to define the edge weight
111 | #E(g2)$weight = 0.1 #define all weights small to visually see as we build sankey
112 | E(g2)[to(V(g2)$weight>0)]$weight <- V(g2)[V(g2)$weight>0]$weight
113 | #and to find the neighbors to the 0 out degree vertex
114 | #we could do V(g2)[nei(degree(g2,mode="out")==0)]
115 | #we have everything we need to build the rest by summing
116 | #these edge weights if there are edges still undefined
117 | #so set up a loop to run until all edges have a defined weight
118 | while(max(is.na(E(g2)$weight))) {
119 | #get.data.frame gives us from, to, and weight
120 | #we will get this to make an easier reference later
121 | df <- get.data.frame(g2)
122 | #now go through each edge and find the sum of all its subedges
123 | #we need to check to make sure out degree of its "to" vertex is not 0
124 | #or we will get 0 since there are no edges for vertex with out degree 0
125 | for (i in 1:nrow(df)) {
126 | x = df[i,]
127 | #sum only those with out degree > 0 or sum will be 0
128 | if(max(df$from==x$to)) {
129 | E(g2)[from(x$from) & to(x$to)]$weight = sum(E(g2)[from(x$to)]$weight)
130 | }
131 | }
132 | }
133 |
134 |
135 | #just a quick check on the adjacency
136 | get.adjacency(g2,sparse = FALSE,attr="weight")
137 |
138 |
139 |
140 |
141 | #E(g2)$weight <- runif(length(E(g2)))
142 | edgelistWeight <- get.data.frame(g2)
143 | colnames(edgelistWeight) <- c("source","target","value")
144 | edgelistWeight$source <- as.character(edgelistWeight$source)
145 | edgelistWeight$target <- as.character(edgelistWeight$target)
146 |
147 | sankeyPlot2 <- rCharts$new()
148 | sankeyPlot2$setLib('.')
149 | sankeyPlot2$setTemplate(script = "layouts/chart.html")
150 |
151 | sankeyPlot2$set(
152 | data = edgelistWeight,
153 | nodeWidth = 15,
154 | nodePadding = 10,
155 | layout = 32,
156 | width = 960,
157 | height = 500
158 | )
159 |
160 | sankeyPlot2
161 |
162 |
163 |
164 | data(pHWebs, package = "cheddar")
165 |
166 | community <- pHWebs[[1]]$trophic.links
167 | community$value <- 1
168 | colnames(community) <- c("source","target", "value")
169 | community$source <- paste0(community$source,"[resource]")
170 |
171 | sankeyPlot <- rCharts$new()
172 | sankeyPlot$setLib('.')
173 | sankeyPlot$setTemplate(script = "layouts/chart.html")
174 |
175 | sankeyPlot$set(
176 | data = community,
177 | nodeWidth = 15,
178 | nodePadding = 10,
179 | layout = 32,
180 | width = 960,
181 | height = 500
182 | )
183 |
184 | sankeyPlot
185 |
186 |
187 |
188 |
189 |
190 | data(Millstream, package = "cheddar")
191 |
192 | community <- pHWebs[[1]]$trophic.links
193 | community$value <- 1
194 | colnames(community) <- c("source","target", "value")
195 | community$source <- paste0(community$source,"[resource]")
196 |
197 | sankeyPlot <- rCharts$new()
198 | sankeyPlot$setLib('.')
199 | sankeyPlot$setTemplate(script = "layouts/chart.html")
200 |
201 | sankeyPlot$set(
202 | data = community,
203 | nodeWidth = 15,
204 | nodePadding = 10,
205 | layout = 32,
206 | width = 960,
207 | height = 500
208 | )
209 |
210 | sankeyPlot
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | ToIgraph <- function(community, weight=NULL)
223 | {
224 | if(is.null(TLPS(community)))
225 | {
226 | stop('The community has no trophic links')
227 | }
228 | else
229 | {
230 | tlps <- TLPS(community, link.properties=weight)
231 | if(!is.null(weight))
232 | {
233 | tlps$weight <- tlps[,weight]
234 | }
235 | return (graph.data.frame(tlps,
236 | vertices=NPS(community),
237 | directed=TRUE))
238 | }
239 | }
240 | data(TL84)
241 | # Unweighted network
242 | TL84.ig <- ToIgraph(TL84)
243 |
244 | edgelist <- data.frame(get.edgelist(TL84.ig),stringsAsFactors = FALSE)
245 | edgelist$value <- rep(1,nrow(edgelist))
246 | colnames(edgelist) <- c("source","target","value")
247 | edgelist$source <- paste0(edgelist$source,"[src]")
248 |
249 | sankeyPlot <- rCharts$new()
250 | sankeyPlot$setLib('.')
251 | sankeyPlot$setTemplate(script = "layouts/chart.html")
252 |
253 | sankeyPlot$set(
254 | data = edgelist,
255 | nodeWidth = 15,
256 | nodePadding = 10,
257 | layout = 32,
258 | width = 960,
259 | height = 500
260 | )
261 |
262 | sankeyPlot
263 |
264 |
265 |
266 | graph.edgelist(as.matrix(edgelist)[,1:2],directed = TRUE)
267 | g <- graph.edgelist(as.matrix(edgelist)[,1:2],directed = TRUE)
268 | a <- get.adjacency(g)
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 | edgelist <- get.data.frame(as.undirected(erdos.renyi.game(n=20,p.or.m=.5,type="gnp",directed=T),mode="collapse"))
277 | edgelist$value <- 1
278 | colnames(edgelist) <- c("source","target","value")
279 | edgelist$source <- paste0(edgelist$source,"[src]")
280 |
281 | sankeyPlot <- rCharts$new()
282 | sankeyPlot$setLib('.')
283 | sankeyPlot$setTemplate(script = "layouts/chart.html")
284 |
285 | sankeyPlot$set(
286 | data = edgelist,
287 | nodeWidth = 15,
288 | nodePadding = 10,
289 | layout = 32,
290 | width = 960,
291 | height = 500
292 | )
293 |
294 | sankeyPlot
--------------------------------------------------------------------------------
/js/sankey.js:
--------------------------------------------------------------------------------
1 | d3.sankey = function() {
2 | var sankey = {},
3 | nodeWidth = 24,
4 | nodePadding = 8,
5 | size = [1, 1],
6 | nodes = [],
7 | links = [];
8 |
9 | sankey.nodeWidth = function(_) {
10 | if (!arguments.length) return nodeWidth;
11 | nodeWidth = +_;
12 | return sankey;
13 | };
14 |
15 | sankey.nodePadding = function(_) {
16 | if (!arguments.length) return nodePadding;
17 | nodePadding = +_;
18 | return sankey;
19 | };
20 |
21 | sankey.nodes = function(_) {
22 | if (!arguments.length) return nodes;
23 | nodes = _;
24 | return sankey;
25 | };
26 |
27 | sankey.links = function(_) {
28 | if (!arguments.length) return links;
29 | links = _;
30 | return sankey;
31 | };
32 |
33 | sankey.size = function(_) {
34 | if (!arguments.length) return size;
35 | size = _;
36 | return sankey;
37 | };
38 |
39 | sankey.layout = function(iterations) {
40 | computeNodeLinks();
41 | computeNodeValues();
42 | computeNodeBreadths();
43 | computeNodeDepths(iterations);
44 | computeLinkDepths();
45 | return sankey;
46 | };
47 |
48 | sankey.relayout = function() {
49 | computeLinkDepths();
50 | return sankey;
51 | };
52 |
53 | sankey.link = function() {
54 | var curvature = .5;
55 |
56 | function link(d) {
57 | var x0 = d.source.x + d.source.dx,
58 | x1 = d.target.x,
59 | xi = d3.interpolateNumber(x0, x1),
60 | x2 = xi(curvature),
61 | x3 = xi(1 - curvature),
62 | y0 = d.source.y + d.sy + d.dy / 2,
63 | y1 = d.target.y + d.ty + d.dy / 2;
64 | return "M" + x0 + "," + y0
65 | + "C" + x2 + "," + y0
66 | + " " + x3 + "," + y1
67 | + " " + x1 + "," + y1;
68 | }
69 |
70 | link.curvature = function(_) {
71 | if (!arguments.length) return curvature;
72 | curvature = +_;
73 | return link;
74 | };
75 |
76 | return link;
77 | };
78 |
79 | // Populate the sourceLinks and targetLinks for each node.
80 | // Also, if the source and target are not objects, assume they are indices.
81 | function computeNodeLinks() {
82 | nodes.forEach(function(node) {
83 | node.sourceLinks = [];
84 | node.targetLinks = [];
85 | });
86 | links.forEach(function(link) {
87 | var source = link.source,
88 | target = link.target;
89 | if (typeof source === "number") source = link.source = nodes[link.source];
90 | if (typeof target === "number") target = link.target = nodes[link.target];
91 | source.sourceLinks.push(link);
92 | target.targetLinks.push(link);
93 | });
94 | }
95 |
96 | // Compute the value (size) of each node by summing the associated links.
97 | function computeNodeValues() {
98 | nodes.forEach(function(node) {
99 | node.value = Math.max(
100 | d3.sum(node.sourceLinks, value),
101 | d3.sum(node.targetLinks, value)
102 | );
103 | });
104 | }
105 |
106 | // Iteratively assign the breadth (x-position) for each node.
107 | // Nodes are assigned the maximum breadth of incoming neighbors plus one;
108 | // nodes with no incoming links are assigned breadth zero, while
109 | // nodes with no outgoing links are assigned the maximum breadth.
110 | function computeNodeBreadths() {
111 | var remainingNodes = nodes,
112 | nextNodes,
113 | x = 0;
114 |
115 | while (remainingNodes.length) {
116 | nextNodes = [];
117 | remainingNodes.forEach(function(node) {
118 | node.x = x;
119 | node.dx = nodeWidth;
120 | node.sourceLinks.forEach(function(link) {
121 | nextNodes.push(link.target);
122 | });
123 | });
124 | remainingNodes = nextNodes;
125 | ++x;
126 | }
127 |
128 | //
129 | moveSinksRight(x);
130 | scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));
131 | }
132 |
133 | function moveSourcesRight() {
134 | nodes.forEach(function(node) {
135 | if (!node.targetLinks.length) {
136 | node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;
137 | }
138 | });
139 | }
140 |
141 | function moveSinksRight(x) {
142 | nodes.forEach(function(node) {
143 | if (!node.sourceLinks.length) {
144 | node.x = x - 1;
145 | }
146 | });
147 | }
148 |
149 | function scaleNodeBreadths(kx) {
150 | nodes.forEach(function(node) {
151 | node.x *= kx;
152 | });
153 | }
154 |
155 | function computeNodeDepths(iterations) {
156 | var nodesByBreadth = d3.nest()
157 | .key(function(d) { return d.x; })
158 | .sortKeys(d3.ascending)
159 | .entries(nodes)
160 | .map(function(d) { return d.values; });
161 |
162 | //
163 | initializeNodeDepth();
164 | resolveCollisions();
165 | for (var alpha = 1; iterations > 0; --iterations) {
166 | relaxRightToLeft(alpha *= .99);
167 | resolveCollisions();
168 | relaxLeftToRight(alpha);
169 | resolveCollisions();
170 | }
171 |
172 | function initializeNodeDepth() {
173 | var ky = d3.min(nodesByBreadth, function(nodes) {
174 | return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);
175 | });
176 |
177 | nodesByBreadth.forEach(function(nodes) {
178 | nodes.forEach(function(node, i) {
179 | node.y = i;
180 | node.dy = node.value * ky;
181 | });
182 | });
183 |
184 | links.forEach(function(link) {
185 | link.dy = link.value * ky;
186 | });
187 | }
188 |
189 | function relaxLeftToRight(alpha) {
190 | nodesByBreadth.forEach(function(nodes, breadth) {
191 | nodes.forEach(function(node) {
192 | if (node.targetLinks.length) {
193 | var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);
194 | node.y += (y - center(node)) * alpha;
195 | }
196 | });
197 | });
198 |
199 | function weightedSource(link) {
200 | return center(link.source) * link.value;
201 | }
202 | }
203 |
204 | function relaxRightToLeft(alpha) {
205 | nodesByBreadth.slice().reverse().forEach(function(nodes) {
206 | nodes.forEach(function(node) {
207 | if (node.sourceLinks.length) {
208 | var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);
209 | node.y += (y - center(node)) * alpha;
210 | }
211 | });
212 | });
213 |
214 | function weightedTarget(link) {
215 | return center(link.target) * link.value;
216 | }
217 | }
218 |
219 | function resolveCollisions() {
220 | nodesByBreadth.forEach(function(nodes) {
221 | var node,
222 | dy,
223 | y0 = 0,
224 | n = nodes.length,
225 | i;
226 |
227 | // Push any overlapping nodes down.
228 | nodes.sort(ascendingDepth);
229 | for (i = 0; i < n; ++i) {
230 | node = nodes[i];
231 | dy = y0 - node.y;
232 | if (dy > 0) node.y += dy;
233 | y0 = node.y + node.dy + nodePadding;
234 | }
235 |
236 | // If the bottommost node goes outside the bounds, push it back up.
237 | dy = y0 - nodePadding - size[1];
238 | if (dy > 0) {
239 | y0 = node.y -= dy;
240 |
241 | // Push any overlapping nodes back up.
242 | for (i = n - 2; i >= 0; --i) {
243 | node = nodes[i];
244 | dy = node.y + node.dy + nodePadding - y0;
245 | if (dy > 0) node.y -= dy;
246 | y0 = node.y;
247 | }
248 | }
249 | });
250 | }
251 |
252 | function ascendingDepth(a, b) {
253 | return a.y - b.y;
254 | }
255 | }
256 |
257 | function computeLinkDepths() {
258 | nodes.forEach(function(node) {
259 | node.sourceLinks.sort(ascendingTargetDepth);
260 | node.targetLinks.sort(ascendingSourceDepth);
261 | });
262 | nodes.forEach(function(node) {
263 | var sy = 0, ty = 0;
264 | node.sourceLinks.forEach(function(link) {
265 | link.sy = sy;
266 | sy += link.dy;
267 | });
268 | node.targetLinks.forEach(function(link) {
269 | link.ty = ty;
270 | ty += link.dy;
271 | });
272 | });
273 |
274 | function ascendingSourceDepth(a, b) {
275 | return a.source.y - b.source.y;
276 | }
277 |
278 | function ascendingTargetDepth(a, b) {
279 | return a.target.y - b.target.y;
280 | }
281 | }
282 |
283 | function center(node) {
284 | return node.y + node.dy / 2;
285 | }
286 |
287 | function value(link) {
288 | return link.value;
289 | }
290 |
291 | return sankey;
292 | };
293 |
--------------------------------------------------------------------------------
/libraries/widgets/d3_sankey/js/sankey.js:
--------------------------------------------------------------------------------
1 | d3.sankey = function() {
2 | var sankey = {},
3 | nodeWidth = 24,
4 | nodePadding = 8,
5 | size = [1, 1],
6 | nodes = [],
7 | links = [];
8 |
9 | sankey.nodeWidth = function(_) {
10 | if (!arguments.length) return nodeWidth;
11 | nodeWidth = +_;
12 | return sankey;
13 | };
14 |
15 | sankey.nodePadding = function(_) {
16 | if (!arguments.length) return nodePadding;
17 | nodePadding = +_;
18 | return sankey;
19 | };
20 |
21 | sankey.nodes = function(_) {
22 | if (!arguments.length) return nodes;
23 | nodes = _;
24 | return sankey;
25 | };
26 |
27 | sankey.links = function(_) {
28 | if (!arguments.length) return links;
29 | links = _;
30 | return sankey;
31 | };
32 |
33 | sankey.size = function(_) {
34 | if (!arguments.length) return size;
35 | size = _;
36 | return sankey;
37 | };
38 |
39 | sankey.layout = function(iterations) {
40 | computeNodeLinks();
41 | computeNodeValues();
42 | computeNodeBreadths();
43 | computeNodeDepths(iterations);
44 | computeLinkDepths();
45 | return sankey;
46 | };
47 |
48 | sankey.relayout = function() {
49 | computeLinkDepths();
50 | return sankey;
51 | };
52 |
53 | sankey.link = function() {
54 | var curvature = .5;
55 |
56 | function link(d) {
57 | var x0 = d.source.x + d.source.dx,
58 | x1 = d.target.x,
59 | xi = d3.interpolateNumber(x0, x1),
60 | x2 = xi(curvature),
61 | x3 = xi(1 - curvature),
62 | y0 = d.source.y + d.sy + d.dy / 2,
63 | y1 = d.target.y + d.ty + d.dy / 2;
64 | return "M" + x0 + "," + y0
65 | + "C" + x2 + "," + y0
66 | + " " + x3 + "," + y1
67 | + " " + x1 + "," + y1;
68 | }
69 |
70 | link.curvature = function(_) {
71 | if (!arguments.length) return curvature;
72 | curvature = +_;
73 | return link;
74 | };
75 |
76 | return link;
77 | };
78 |
79 | // Populate the sourceLinks and targetLinks for each node.
80 | // Also, if the source and target are not objects, assume they are indices.
81 | function computeNodeLinks() {
82 | nodes.forEach(function(node) {
83 | node.sourceLinks = [];
84 | node.targetLinks = [];
85 | });
86 | links.forEach(function(link) {
87 | var source = link.source,
88 | target = link.target;
89 | if (typeof source === "number") source = link.source = nodes[link.source];
90 | if (typeof target === "number") target = link.target = nodes[link.target];
91 | source.sourceLinks.push(link);
92 | target.targetLinks.push(link);
93 | });
94 | }
95 |
96 | // Compute the value (size) of each node by summing the associated links.
97 | function computeNodeValues() {
98 | nodes.forEach(function(node) {
99 | node.value = Math.max(
100 | d3.sum(node.sourceLinks, value),
101 | d3.sum(node.targetLinks, value)
102 | );
103 | });
104 | }
105 |
106 | // Iteratively assign the breadth (x-position) for each node.
107 | // Nodes are assigned the maximum breadth of incoming neighbors plus one;
108 | // nodes with no incoming links are assigned breadth zero, while
109 | // nodes with no outgoing links are assigned the maximum breadth.
110 | function computeNodeBreadths() {
111 | var remainingNodes = nodes,
112 | nextNodes,
113 | x = 0;
114 |
115 | while (remainingNodes.length) {
116 | nextNodes = [];
117 | remainingNodes.forEach(function(node) {
118 | node.x = x;
119 | node.dx = nodeWidth;
120 | node.sourceLinks.forEach(function(link) {
121 | nextNodes.push(link.target);
122 | });
123 | });
124 | remainingNodes = nextNodes;
125 | ++x;
126 | }
127 |
128 | //
129 | moveSinksRight(x);
130 | scaleNodeBreadths((size[0] - nodeWidth) / (x - 1));
131 | }
132 |
133 | function moveSourcesRight() {
134 | nodes.forEach(function(node) {
135 | if (!node.targetLinks.length) {
136 | node.x = d3.min(node.sourceLinks, function(d) { return d.target.x; }) - 1;
137 | }
138 | });
139 | }
140 |
141 | function moveSinksRight(x) {
142 | nodes.forEach(function(node) {
143 | if (!node.sourceLinks.length) {
144 | node.x = x - 1;
145 | }
146 | });
147 | }
148 |
149 | function scaleNodeBreadths(kx) {
150 | nodes.forEach(function(node) {
151 | node.x *= kx;
152 | });
153 | }
154 |
155 | function computeNodeDepths(iterations) {
156 | var nodesByBreadth = d3.nest()
157 | .key(function(d) { return d.x; })
158 | .sortKeys(d3.ascending)
159 | .entries(nodes)
160 | .map(function(d) { return d.values; });
161 |
162 | //
163 | initializeNodeDepth();
164 | resolveCollisions();
165 | for (var alpha = 1; iterations > 0; --iterations) {
166 | relaxRightToLeft(alpha *= .99);
167 | resolveCollisions();
168 | relaxLeftToRight(alpha);
169 | resolveCollisions();
170 | }
171 |
172 | function initializeNodeDepth() {
173 | var ky = d3.min(nodesByBreadth, function(nodes) {
174 | return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value);
175 | });
176 |
177 | nodesByBreadth.forEach(function(nodes) {
178 | nodes.forEach(function(node, i) {
179 | node.y = i;
180 | node.dy = node.value * ky;
181 | });
182 | });
183 |
184 | links.forEach(function(link) {
185 | link.dy = link.value * ky;
186 | });
187 | }
188 |
189 | function relaxLeftToRight(alpha) {
190 | nodesByBreadth.forEach(function(nodes, breadth) {
191 | nodes.forEach(function(node) {
192 | if (node.targetLinks.length) {
193 | var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value);
194 | node.y += (y - center(node)) * alpha;
195 | }
196 | });
197 | });
198 |
199 | function weightedSource(link) {
200 | return center(link.source) * link.value;
201 | }
202 | }
203 |
204 | function relaxRightToLeft(alpha) {
205 | nodesByBreadth.slice().reverse().forEach(function(nodes) {
206 | nodes.forEach(function(node) {
207 | if (node.sourceLinks.length) {
208 | var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value);
209 | node.y += (y - center(node)) * alpha;
210 | }
211 | });
212 | });
213 |
214 | function weightedTarget(link) {
215 | return center(link.target) * link.value;
216 | }
217 | }
218 |
219 | function resolveCollisions() {
220 | nodesByBreadth.forEach(function(nodes) {
221 | var node,
222 | dy,
223 | y0 = 0,
224 | n = nodes.length,
225 | i;
226 |
227 | // Push any overlapping nodes down.
228 | nodes.sort(ascendingDepth);
229 | for (i = 0; i < n; ++i) {
230 | node = nodes[i];
231 | dy = y0 - node.y;
232 | if (dy > 0) node.y += dy;
233 | y0 = node.y + node.dy + nodePadding;
234 | }
235 |
236 | // If the bottommost node goes outside the bounds, push it back up.
237 | dy = y0 - nodePadding - size[1];
238 | if (dy > 0) {
239 | y0 = node.y -= dy;
240 |
241 | // Push any overlapping nodes back up.
242 | for (i = n - 2; i >= 0; --i) {
243 | node = nodes[i];
244 | dy = node.y + node.dy + nodePadding - y0;
245 | if (dy > 0) node.y -= dy;
246 | y0 = node.y;
247 | }
248 | }
249 | });
250 | }
251 |
252 | function ascendingDepth(a, b) {
253 | return a.y - b.y;
254 | }
255 | }
256 |
257 | function computeLinkDepths() {
258 | nodes.forEach(function(node) {
259 | node.sourceLinks.sort(ascendingTargetDepth);
260 | node.targetLinks.sort(ascendingSourceDepth);
261 | });
262 | nodes.forEach(function(node) {
263 | var sy = 0, ty = 0;
264 | node.sourceLinks.forEach(function(link) {
265 | link.sy = sy;
266 | sy += link.dy;
267 | });
268 | node.targetLinks.forEach(function(link) {
269 | link.ty = ty;
270 | ty += link.dy;
271 | });
272 | });
273 |
274 | function ascendingSourceDepth(a, b) {
275 | return a.source.y - b.source.y;
276 | }
277 |
278 | function ascendingTargetDepth(a, b) {
279 | return a.target.y - b.target.y;
280 | }
281 | }
282 |
283 | function center(node) {
284 | return node.y + node.dy / 2;
285 | }
286 |
287 | function value(link) {
288 | return link.value;
289 | }
290 |
291 | return sankey;
292 | };
293 |
--------------------------------------------------------------------------------
/libraries/frameworks/bootstrap/css/bootstrap-responsive.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.1.1
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade.in{top:auto}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:block;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
10 |
--------------------------------------------------------------------------------
/example_build_network_sankey.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Sankey from Scratch
3 | author: Timely Portfolio
4 | github: {user: timelyportfolio, repo: rCharts_d3_horizon, branch: "gh-pages"}
5 | framework: bootstrap
6 | mode: selfcontained
7 | highlighter: prettify
8 | hitheme: twitter-bootstrap
9 | widgets: "d3_sankey"
10 | assets:
11 | css:
12 | - "http://fonts.googleapis.com/css?family=Raleway:300"
13 | - "http://fonts.googleapis.com/css?family=Oxygen"
14 | ---
15 |
16 |
38 |
39 |
40 |
41 |
42 |
43 | # Sankey from Scratch using `rCharts`, `d3.js`, and `igraph`
44 |
45 | ## Introduction
46 |
47 | This example will walk through the steps of using the `R` package [`igraph`](http://igraph.sourceforge.net/) to create a tree network for a [sankey diagram](http://econ.st/JwNX8s). This is a great exercise to learn some basics of `igraph`, explore the construction of a sankey, and determine the conditions for a network to be drawn properly as a sankey. After all of this, we will plot our network with the [`rCharts`](http://rcharts.io/site) implementation of the [d3.js sankey plugin](https://github.com/d3/d3-plugins/blob/master/sankey/sankey.js).
48 |
49 |
50 | ## Build a Network
51 | Let's first start by loading the `igraph` and `rCharts` packages. Then we will use `graph.tree` to build a tree network with 40 vertices with 4 children.
52 |
53 | ```r
54 | require(igraph)
55 | require(rCharts)
56 |
57 | g <- graph.tree(40, children = 4)
58 | ```
59 |
60 | For fun, we will assign a weight of 1 `E(g)$weight = 1` for each edge and then draw a Sankey diagram using `rCharts`. Going forward I will try to explain the `R` code through comments in the code block.
61 |
62 | ## Plot Our Sankey to Find a Problem
63 |
64 | ```r
65 | E(g)$weight = 1
66 |
67 | edgelist <- get.data.frame(g) #this will give us a data frame with from,to,weight
68 | colnames(edgelist) <- c("source","target","value")
69 | #make character rather than numeric for proper functioning
70 | edgelist$source <- as.character(edgelist$source)
71 | edgelist$target <- as.character(edgelist$target)
72 |
73 | sankeyPlot <- rCharts$new()
74 | sankeyPlot$setLib('libraries/widgets/d3_sankey')
75 | sankeyPlot$setTemplate(script = "libraries/widgets/d3_sankey/layouts/chart.html")
76 |
77 | sankeyPlot$set(
78 | data = edgelist,
79 | nodeWidth = 15,
80 | nodePadding = 10,
81 | layout = 32,
82 | width = 960,
83 | height = 500
84 | )
85 |
86 | sankeyPlot$print(chartId = 'sankey1')
87 | ```
88 |
89 |
90 |
91 |
95 |
96 |
220 |
221 |
222 | Interact with the sankey plot a little, and try to find the problem in our hastily constructed network. Hovering over the vertex 4 will reveal our issue. The edge from 1 to 4 is not as big as the sum of the edges going out from 4. For this to make sense, unless 4 is magically creating something, the sum of the inflow should equal the sum of the outflow. Since 4 has four children each with weight of 1 (outflow = 1 + 1 + 1 + 1 = 4), we would expect the inflow to also be 4. It is only 1 though since we made all our edges' weights = 1 `E(g)$weight = 1`. How then would we build our network with edge weights so that for each vertex, the sum of in equals the sum of out.
223 |
224 |
225 | ## Fix Our Problem For a Beautiful Sankey
226 | I am a network novice, so while the code below works, I am sure there are better ways of accomplishing the desired result. I heavily commented the code, but I will quickly describe the steps. The code starts at the lowest level of the heirarchy, or those vertexes where there is nothing going out (out degree = 0). In our network, these are 11 through 40. With `igraph` we can identify these by `V(g2)[degree(g2,mode="out")==0]`. For these we will assign a weight. Then we will loop through all of the edges summing all of the weights of the out until we have reached the top of the heirarchy.
227 |
228 |
229 | ```r
230 | g2 <- graph.tree(40, children=4)
231 | #to construct a sankey the weight of each vertex should be the sum
232 | #of its outgoing edges
233 | #I believe the first step in creating a network that satisfies this condition
234 | #is define a vertex weight for all vertexes with out degree = 0
235 | #but first let's define 0 for all
236 | V(g2)$weight = 0
237 | #now for all vertexes with out degree = 0
238 | V(g2)[degree(g2,mode="out")==0]$weight <- runif(n=length(V(g2)[degree(g2,mode="out")==0]),min=0,max=100)
239 | #the lowest level of the heirarchy is defined with a random weight
240 | #with the lowest level defined we should now be able to sum the vertex weights
241 | #to define the edge weight
242 | #E(g2)$weight = 0.1 #define all weights small to visually see as we build sankey
243 | E(g2)[to(V(g2)$weight>0)]$weight <- V(g2)[V(g2)$weight>0]$weight
244 | #and to find the neighbors to the 0 out degree vertex
245 | #we could do V(g2)[nei(degree(g2,mode="out")==0)]
246 | #we have everything we need to build the rest by summing
247 | #these edge weights if there are edges still undefined
248 | #so set up a loop to run until all edges have a defined weight
249 | while(max(is.na(E(g2)$weight))) {
250 | #get.data.frame gives us from, to, and weight
251 | #we will get this to make an easier reference later
252 | df <- get.data.frame(g2)
253 | #now go through each edge and find the sum of all its subedges
254 | #we need to check to make sure out degree of its "to" vertex is not 0
255 | #or we will get 0 since there are no edges for vertex with out degree 0
256 | for (i in 1:nrow(df)) {
257 | x = df[i,]
258 | #sum only those with out degree > 0 or sum will be 0
259 | if(max(df$from==x$to)) {
260 | E(g2)[from(x$from) & to(x$to)]$weight = sum(E(g2)[from(x$to)]$weight)
261 | }
262 | }
263 | }
264 |
265 | edgelistWeight <- get.data.frame(g2)
266 | colnames(edgelistWeight) <- c("source","target","value")
267 | edgelistWeight$source <- as.character(edgelistWeight$source)
268 | edgelistWeight$target <- as.character(edgelistWeight$target)
269 |
270 | sankeyPlot2 <- rCharts$new()
271 | sankeyPlot2$setLib('libraries/widgets/d3_sankey')
272 | sankeyPlot2$setTemplate(script = 'libraries/widgets/d3_sankey/layouts/chart.html')
273 |
274 | sankeyPlot2$set(
275 | data = edgelistWeight,
276 | nodeWidth = 15,
277 | nodePadding = 10,
278 | layout = 32,
279 | width = 960,
280 | height = 500
281 | )
282 |
283 | sankeyPlot2
284 | ```
285 |
286 |
287 |
288 |
292 |
293 |
417 |
418 |
419 | ## Another Look at Our Network
420 | There are very [good examples](http://rulesofreason.wordpress.com/tag/plot-igraph/) illustrating the use of `igraph` to plot a network. This is not one of these examples. For fun though, let's plot the network with igraph using just the defaults to compare it to our Sankey output from above.
421 |
422 |
423 | ```r
424 | plot(g2)
425 | ```
426 |
427 | 
428 |
429 |
430 | ## Lots More Sankey
431 | Believe it or not, there is an entire site devoted to sankey diagrams. For all the sankey you can handle, check out http://sankey-diagrams.com. Here are a couple more sankeys generated from `rCharts`: http://rcharts.io/viewer/?6001601#.UeWfuY3VCSo, http://rcharts.io/viewer/?6003605, http://rcharts.io/viewer/?6003575.
432 |
--------------------------------------------------------------------------------
/libraries/frameworks/bootstrap/js/vendor/modernizr-2.6.1-respond-1.1.0.min.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.6.1 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;drCharts, d3.js, and igraphThis example will walk through the steps of using the R package igraph to create a tree network for a sankey diagram. This is a great exercise to learn some basics of igraph, explore the construction of a sankey, and determine the conditions for a network to be drawn properly as a sankey. After all of this, we will plot our network with the rCharts implementation of the d3.js sankey plugin.
Let's first start by loading the igraph and rCharts packages. Then we will use graph.tree to build a tree network with 40 vertices with 4 children.
require(igraph)
88 | require(rCharts)
89 |
90 | g <- graph.tree(40, children = 4)
91 |
92 |
93 | For fun, we will assign a weight of 1 E(g)$weight = 1 for each edge and then draw a Sankey diagram using rCharts. Going forward I will try to explain the R code through comments in the code block.
E(g)$weight = 1
98 |
99 | edgelist <- get.data.frame(g) #this will give us a data frame with from,to,weight
100 | colnames(edgelist) <- c("source","target","value")
101 | #make character rather than numeric for proper functioning
102 | edgelist$source <- as.character(edgelist$source)
103 | edgelist$target <- as.character(edgelist$target)
104 |
105 | sankeyPlot <- rCharts$new()
106 | sankeyPlot$setLib('libraries/widgets/d3_sankey')
107 | sankeyPlot$setTemplate(script = "libraries/widgets/d3_sankey/layouts/chart.html")
108 |
109 | sankeyPlot$set(
110 | data = edgelist,
111 | nodeWidth = 15,
112 | nodePadding = 10,
113 | layout = 32,
114 | width = 960,
115 | height = 500
116 | )
117 |
118 | sankeyPlot$print(chartId = 'sankey1')
119 |
120 |
121 |
122 |
123 |
127 |
128 |
254 |
255 | Interact with the sankey plot a little, and try to find the problem in our hastily constructed network. Hovering over the vertex 4 will reveal our issue. The edge from 1 to 4 is not as big as the sum of the edges going out from 4. For this to make sense, unless 4 is magically creating something, the sum of the inflow should equal the sum of the outflow. Since 4 has four children each with weight of 1 (outflow = 1 + 1 + 1 + 1 = 4), we would expect the inflow to also be 4. It is only 1 though since we made all our edges' weights = 1 E(g)$weight = 1. How then would we build our network with edge weights so that for each vertex, the sum of in equals the sum of out.
I am a network novice, so while the code below works, I am sure there are better ways of accomplishing the desired result. I heavily commented the code, but I will quickly describe the steps. The code starts at the lowest level of the heirarchy, or those vertexes where there is nothing going out (out degree = 0). In our network, these are 11 through 40. With igraph we can identify these by V(g2)[degree(g2,mode="out")==0]. For these we will assign a weight. Then we will loop through all of the edges summing all of the weights of the out until we have reached the top of the heirarchy.
g2 <- graph.tree(40, children=4)
262 | #to construct a sankey the weight of each vertex should be the sum
263 | #of its outgoing edges
264 | #I believe the first step in creating a network that satisfies this condition
265 | #is define a vertex weight for all vertexes with out degree = 0
266 | #but first let's define 0 for all
267 | V(g2)$weight = 0
268 | #now for all vertexes with out degree = 0
269 | V(g2)[degree(g2,mode="out")==0]$weight <- runif(n=length(V(g2)[degree(g2,mode="out")==0]),min=0,max=100)
270 | #the lowest level of the heirarchy is defined with a random weight
271 | #with the lowest level defined we should now be able to sum the vertex weights
272 | #to define the edge weight
273 | #E(g2)$weight = 0.1 #define all weights small to visually see as we build sankey
274 | E(g2)[to(V(g2)$weight>0)]$weight <- V(g2)[V(g2)$weight>0]$weight
275 | #and to find the neighbors to the 0 out degree vertex
276 | #we could do V(g2)[nei(degree(g2,mode="out")==0)]
277 | #we have everything we need to build the rest by summing
278 | #these edge weights if there are edges still undefined
279 | #so set up a loop to run until all edges have a defined weight
280 | while(max(is.na(E(g2)$weight))) {
281 | #get.data.frame gives us from, to, and weight
282 | #we will get this to make an easier reference later
283 | df <- get.data.frame(g2)
284 | #now go through each edge and find the sum of all its subedges
285 | #we need to check to make sure out degree of its "to" vertex is not 0
286 | #or we will get 0 since there are no edges for vertex with out degree 0
287 | for (i in 1:nrow(df)) {
288 | x = df[i,]
289 | #sum only those with out degree > 0 or sum will be 0
290 | if(max(df$from==x$to)) {
291 | E(g2)[from(x$from) & to(x$to)]$weight = sum(E(g2)[from(x$to)]$weight)
292 | }
293 | }
294 | }
295 |
296 | edgelistWeight <- get.data.frame(g2)
297 | colnames(edgelistWeight) <- c("source","target","value")
298 | edgelistWeight$source <- as.character(edgelistWeight$source)
299 | edgelistWeight$target <- as.character(edgelistWeight$target)
300 |
301 | sankeyPlot2 <- rCharts$new()
302 | sankeyPlot2$setLib('libraries/widgets/d3_sankey')
303 | sankeyPlot2$setTemplate(script = 'libraries/widgets/d3_sankey/layouts/chart.html')
304 |
305 | sankeyPlot2$set(
306 | data = edgelistWeight,
307 | nodeWidth = 15,
308 | nodePadding = 10,
309 | layout = 32,
310 | width = 960,
311 | height = 500
312 | )
313 |
314 | sankeyPlot2
315 |
316 |
317 |
318 |
319 |
323 |
324 |
450 |
451 | There are very good examples illustrating the use of igraph to plot a network. This is not one of these examples. For fun though, let's plot the network with igraph using just the defaults to compare it to our Sankey output from above.
plot(g2)
456 |
457 |
458 |
Believe it or not, there is an entire site devoted to sankey diagrams. For all the sankey you can handle, check out http://sankey-diagrams.com. Here are a couple more sankeys generated from rCharts: http://rcharts.io/viewer/?6001601#.UeWfuY3VCSo, http://rcharts.io/viewer/?6003605, http://rcharts.io/viewer/?6003575.