d3Network/0000755000176200001440000000000012463201366012135 5ustar liggesusersd3Network/NAMESPACE0000644000176200001440000000045612463141360013356 0ustar liggesusers# Generated by roxygen2 (4.0.1): do not edit by hand export(JSONtoDF) export(d3ClusterDendro) export(d3ForceNetwork) export(d3Network) export(d3Sankey) export(d3SimpleNetwork) export(d3Tree) importFrom(plyr,ldply) importFrom(rjson,fromJSON) importFrom(rjson,toJSON) importFrom(whisker,whisker.render) d3Network/NEWS0000644000176200001440000000464112463141360012636 0ustar liggesusers## v0.5.2.1 Trivial change to deal with deficiency in CRAN Markdown processor. ## v0.5.2 Fixed a bug in `d3Sankey` that prevented the `parentElement` from being customisable selected. Thanks to Bo Werth for identifying this. ## v0.5.1 Added `linkWidth` to `d3ForceNetwork` in order to set the link width. An absolute numeric width can be set as well as a JavaScript function for weighting by `Value`. Improved documentation to demonstrate how a JavaScript function can be added to `linkDistance`, possibly to weight the distance by `Value`. Thanks to Kevin Keenan for the suggestion. Improvements to `iframe` width/height calculation for `d3SimpleNetwork`. Removed 'TWh' from `d3Sankey`'s number format. Thanks to Enzo Martoglio for spotting this. Documentation improvements. ## v0.5 `parentElement` argument added to all d3Network functions. It allows the user to specify the resulting svg graph's parent element. This is especially handy for use with Shiny server. Thanks to John Harrison. Minor documentation improvements. Internal code cleaning. ## v0.4.2 Minor bug fix for `d3ForceNetwork`. ## v0.4.1 Improve `d3ForceNetwork` documentation. ## v0.4 Added `d3Sankey` to create Sankey diagrams. Thanks to Scott Chamberlain for the suggestion. ## v0.3.3 `toJSONarray` no longer quotes integers. Thanks to Mark Gene. ## v0.3.2 Change examples for `d3ClusterDendro` so that they run on Windows. ## v0.3.1 Collapse and expand clustered dendrograms. Mouse over zooming with clustered dendrograms. ## v0.3 Added Reingold–Tilford Tree graph with `d3Tree`. Added Cluster Denograms with `d3ClusterDendro`. ## v0.2.1 Added ability to zoom into and out of graphs with `zoom` option for `d3ForceNetwork`. `d3ForceNetwork` example now uses tabular data. ## v0.2 Added `d3ForceNetwork` for creating force directed network graphs where link distance and group changes the graphs attributes. `d3SimpleNetwork` and `d3Network` are now the same and have improved aesthetic customisability. `d3Network` is depricated. This is in advance of creating functions for force directed and other types of networks. `JSONtoDF` command added for reading a JSON data file into R. It converts a specified array in the JSON data into a data frame. Improvements to the internal workings of the commands. Now uses mustache templates to create the graphs. Documentation and minor bug fixes. ## v0.1.2 Internal improvements using whisker templating. d3Network/data/0000755000176200001440000000000012463141360013043 5ustar liggesusersd3Network/data/MisLinks.tab0000644000176200001440000000661012463141360015267 0ustar liggesusers"source" "target" "value" "1" 1 0 1 "2" 2 0 8 "3" 3 0 10 "4" 3 2 6 "5" 4 0 1 "6" 5 0 1 "7" 6 0 1 "8" 7 0 1 "9" 8 0 2 "10" 9 0 1 "11" 11 10 1 "12" 11 3 3 "13" 11 2 3 "14" 11 0 5 "15" 12 11 1 "16" 13 11 1 "17" 14 11 1 "18" 15 11 1 "19" 17 16 4 "20" 18 16 4 "21" 18 17 4 "22" 19 16 4 "23" 19 17 4 "24" 19 18 4 "25" 20 16 3 "26" 20 17 3 "27" 20 18 3 "28" 20 19 4 "29" 21 16 3 "30" 21 17 3 "31" 21 18 3 "32" 21 19 3 "33" 21 20 5 "34" 22 16 3 "35" 22 17 3 "36" 22 18 3 "37" 22 19 3 "38" 22 20 4 "39" 22 21 4 "40" 23 16 3 "41" 23 17 3 "42" 23 18 3 "43" 23 19 3 "44" 23 20 4 "45" 23 21 4 "46" 23 22 4 "47" 23 12 2 "48" 23 11 9 "49" 24 23 2 "50" 24 11 7 "51" 25 24 13 "52" 25 23 1 "53" 25 11 12 "54" 26 24 4 "55" 26 11 31 "56" 26 16 1 "57" 26 25 1 "58" 27 11 17 "59" 27 23 5 "60" 27 25 5 "61" 27 24 1 "62" 27 26 1 "63" 28 11 8 "64" 28 27 1 "65" 29 23 1 "66" 29 27 1 "67" 29 11 2 "68" 30 23 1 "69" 31 30 2 "70" 31 11 3 "71" 31 23 2 "72" 31 27 1 "73" 32 11 1 "74" 33 11 2 "75" 33 27 1 "76" 34 11 3 "77" 34 29 2 "78" 35 11 3 "79" 35 34 3 "80" 35 29 2 "81" 36 34 2 "82" 36 35 2 "83" 36 11 2 "84" 36 29 1 "85" 37 34 2 "86" 37 35 2 "87" 37 36 2 "88" 37 11 2 "89" 37 29 1 "90" 38 34 2 "91" 38 35 2 "92" 38 36 2 "93" 38 37 2 "94" 38 11 2 "95" 38 29 1 "96" 39 25 1 "97" 40 25 1 "98" 41 24 2 "99" 41 25 3 "100" 42 41 2 "101" 42 25 2 "102" 42 24 1 "103" 43 11 3 "104" 43 26 1 "105" 43 27 1 "106" 44 28 3 "107" 44 11 1 "108" 45 28 2 "109" 47 46 1 "110" 48 47 2 "111" 48 25 1 "112" 48 27 1 "113" 48 11 1 "114" 49 26 3 "115" 49 11 2 "116" 50 49 1 "117" 50 24 1 "118" 51 49 9 "119" 51 26 2 "120" 51 11 2 "121" 52 51 1 "122" 52 39 1 "123" 53 51 1 "124" 54 51 2 "125" 54 49 1 "126" 54 26 1 "127" 55 51 6 "128" 55 49 12 "129" 55 39 1 "130" 55 54 1 "131" 55 26 21 "132" 55 11 19 "133" 55 16 1 "134" 55 25 2 "135" 55 41 5 "136" 55 48 4 "137" 56 49 1 "138" 56 55 1 "139" 57 55 1 "140" 57 41 1 "141" 57 48 1 "142" 58 55 7 "143" 58 48 7 "144" 58 27 6 "145" 58 57 1 "146" 58 11 4 "147" 59 58 15 "148" 59 55 5 "149" 59 48 6 "150" 59 57 2 "151" 60 48 1 "152" 60 58 4 "153" 60 59 2 "154" 61 48 2 "155" 61 58 6 "156" 61 60 2 "157" 61 59 5 "158" 61 57 1 "159" 61 55 1 "160" 62 55 9 "161" 62 58 17 "162" 62 59 13 "163" 62 48 7 "164" 62 57 2 "165" 62 41 1 "166" 62 61 6 "167" 62 60 3 "168" 63 59 5 "169" 63 48 5 "170" 63 62 6 "171" 63 57 2 "172" 63 58 4 "173" 63 61 3 "174" 63 60 2 "175" 63 55 1 "176" 64 55 5 "177" 64 62 12 "178" 64 48 5 "179" 64 63 4 "180" 64 58 10 "181" 64 61 6 "182" 64 60 2 "183" 64 59 9 "184" 64 57 1 "185" 64 11 1 "186" 65 63 5 "187" 65 64 7 "188" 65 48 3 "189" 65 62 5 "190" 65 58 5 "191" 65 61 5 "192" 65 60 2 "193" 65 59 5 "194" 65 57 1 "195" 65 55 2 "196" 66 64 3 "197" 66 58 3 "198" 66 59 1 "199" 66 62 2 "200" 66 65 2 "201" 66 48 1 "202" 66 63 1 "203" 66 61 1 "204" 66 60 1 "205" 67 57 3 "206" 68 25 5 "207" 68 11 1 "208" 68 24 1 "209" 68 27 1 "210" 68 48 1 "211" 68 41 1 "212" 69 25 6 "213" 69 68 6 "214" 69 11 1 "215" 69 24 1 "216" 69 27 2 "217" 69 48 1 "218" 69 41 1 "219" 70 25 4 "220" 70 69 4 "221" 70 68 4 "222" 70 11 1 "223" 70 24 1 "224" 70 27 1 "225" 70 41 1 "226" 70 58 1 "227" 71 27 1 "228" 71 69 2 "229" 71 68 2 "230" 71 70 2 "231" 71 11 1 "232" 71 48 1 "233" 71 41 1 "234" 71 25 1 "235" 72 26 2 "236" 72 27 1 "237" 72 11 1 "238" 73 48 2 "239" 74 48 2 "240" 74 73 3 "241" 75 69 3 "242" 75 68 3 "243" 75 25 3 "244" 75 48 1 "245" 75 41 1 "246" 75 70 1 "247" 75 71 1 "248" 76 64 1 "249" 76 65 1 "250" 76 66 1 "251" 76 63 1 "252" 76 62 1 "253" 76 48 1 "254" 76 58 1 d3Network/data/MisNodes.tab0000644000176200001440000000266612463141360015266 0ustar liggesusers"name" "group" "1" "Myriel" 1 "2" "Napoleon" 1 "3" "Mlle.Baptistine" 1 "4" "Mme.Magloire" 1 "5" "CountessdeLo" 1 "6" "Geborand" 1 "7" "Champtercier" 1 "8" "Cravatte" 1 "9" "Count" 1 "10" "OldMan" 1 "11" "Labarre" 2 "12" "Valjean" 2 "13" "Marguerite" 3 "14" "Mme.deR" 2 "15" "Isabeau" 2 "16" "Gervais" 2 "17" "Tholomyes" 3 "18" "Listolier" 3 "19" "Fameuil" 3 "20" "Blacheville" 3 "21" "Favourite" 3 "22" "Dahlia" 3 "23" "Zephine" 3 "24" "Fantine" 3 "25" "Mme.Thenardier" 4 "26" "Thenardier" 4 "27" "Cosette" 5 "28" "Javert" 4 "29" "Fauchelevent" 0 "30" "Bamatabois" 2 "31" "Perpetue" 3 "32" "Simplice" 2 "33" "Scaufflaire" 2 "34" "Woman1" 2 "35" "Judge" 2 "36" "Champmathieu" 2 "37" "Brevet" 2 "38" "Chenildieu" 2 "39" "Cochepaille" 2 "40" "Pontmercy" 4 "41" "Boulatruelle" 6 "42" "Eponine" 4 "43" "Anzelma" 4 "44" "Woman2" 5 "45" "MotherInnocent" 0 "46" "Gribier" 0 "47" "Jondrette" 7 "48" "Mme.Burgon" 7 "49" "Gavroche" 8 "50" "Gillenormand" 5 "51" "Magnon" 5 "52" "Mlle.Gillenormand" 5 "53" "Mme.Pontmercy" 5 "54" "Mlle.Vaubois" 5 "55" "Lt.Gillenormand" 5 "56" "Marius" 8 "57" "BaronessT" 5 "58" "Mabeuf" 8 "59" "Enjolras" 8 "60" "Combeferre" 8 "61" "Prouvaire" 8 "62" "Feuilly" 8 "63" "Courfeyrac" 8 "64" "Bahorel" 8 "65" "Bossuet" 8 "66" "Joly" 8 "67" "Grantaire" 8 "68" "MotherPlutarch" 9 "69" "Gueulemer" 4 "70" "Babet" 4 "71" "Claquesous" 4 "72" "Montparnasse" 4 "73" "Toussaint" 5 "74" "Child1" 10 "75" "Child2" 10 "76" "Brujon" 4 "77" "Mme.Hucheloup" 8 d3Network/R/0000755000176200001440000000000012463141360012333 5ustar liggesusersd3Network/R/utils.R0000644000176200001440000000502012463141360013613 0ustar liggesusers#' Read a link-node structured JSON file into R as two data frames. #' #' \code{JSONtoDF} reads a JSON data file into R and converts part of it to a #' data frame. #' #' @param jsonStr a JSON object to convert. Note if \code{jsonStr} is specified, #' then \code{file} must be \code{NULL}. #' @param file character string of the JSON file name. Note if \code{file} is #' specified, then \code{jsonStr} must be \code{NULL}. #' @param array character string specifying the name of the JSON array to #' extract. (JSON arrays are delimited by square brackets). #' #' @details \code{JSONtoDF} is intended to load JSON files into R and convert #' them to data frames that can be used to create network graphs. The command #' converts the files into R lists and then extracts the JSON array the user #' would like to make into a data frame. #' #' @source Part of the idea for the command comes from mropa's comment on #' StackExchange: #' \url{http://stackoverflow.com/questions/4227223/r-list-to-data-frame}. #' #' @importFrom rjson fromJSON #' @importFrom plyr ldply #' @export JSONtoDF <- function(jsonStr = NULL, file = NULL, array){ if (!is.null(jsonStr) & !is.null(file)){ stop("Must specify jsonStr OR file.") } if (is.null(file)){ MainList <- fromJSON(json_str = jsonStr) } if (is.null(jsonStr)){ MainList <- fromJSON(file = file) } ArrayList <- MainList[[array]] MainDF <- ldply(ArrayList, data.frame) return(MainDF) } #' Internal function from Wei Luo to convert a data frame to a JSON array #' #' @param dtf a data frame object. #' @source Function from: #' \url{http://theweiluo.wordpress.com/2011/09/30/r-to-json-for-d3-js-and-protovis/} #' @keywords internal #' @noRd toJSONarray <- function(dtf){ clnms <- colnames(dtf) name.value <- function(i){ quote <- ''; if(class(dtf[, i])!='numeric' && class(dtf[, i])!='integer'){ quote <- '"'; } paste('"', i, '" : ', quote, dtf[,i], quote, sep='') } objs <- apply(sapply(clnms, name.value), 1, function(x){paste(x, collapse=', ')}) objs <- paste('{', objs, '}') res <- paste('[', paste(objs, collapse=', '), ']') return(res) } #' Read a text file into a single string #' #' @source Code taken directly from Ramnath Vaidyanathan's Slidify #' \url{https://github.com/ramnathv/slidify}. #' @param doc path to text document #' @return string with document contents #' @keywords internal #' @noRd read_file <- function(doc, ...){ paste(readLines(doc, ...), collapse = '\n') } d3Network/R/DataDescriptions.R0000644000176200001440000000212512463141360015716 0ustar liggesusers#' A data file of nodes from Knuth's Les Miserables characters data base. #' #' @docType data #' @source See Mike Bostock \url{http://bl.ocks.org/mbostock/4062045}. #' @keywords datasets #' @format A data set with 77 observations of 2 variables. #' @name MisNodes #' NULL #' A data file of links from Knuth's Les Miserables characters data base. #' #' @docType data #' @source See Mike Bostock \url{http://bl.ocks.org/mbostock/4062045}. #' @keywords datasets #' @format A data set with 254 observations of 3 variables. #' @name MisLinks #' NULL #' JSON data file of the Flare class hierarchy. #' #' @docType data #' @source See Mike Bostock \url{http://bl.ocks.org/mbostock/4063550}. #' @keywords datasets #' @format A JSON file with two arrays \code{name} and \code{children}. #' @name flare #' NULL #' JSON data file of a projection of UK energy production and consumption in 2050. #' #' @docType data #' @source See Mike Bostock \url{http://bost.ocks.org/mike/sankey/}. #' @keywords datasets #' @format A JSON file with two arrays \code{nodes} and \code{links}. #' @name energy #' NULLd3Network/R/d3ClusterDendro.R0000644000176200001440000001333512463141360015467 0ustar liggesusers#' Create a D3 JavaScript Cluster Dendrogram graphs. #' #' #' @param List a hierarchical list object with a root node and children. #' @param height numeric height for the network graph's frame area in pixels. #' @param width numeric width for the network graph's frame area in pixels. #' @param heightCollapse numeric proportion of the overall graph \code{height} #' to make the cluster dendrogram shorter by. #' @param widthCollapse numeric proportion of the overall graph \code{width} to #' make the cluster dendrogram narrower by. #' @param fontsize numeric font size in pixels for the node text labels. #' @param linkColour character string specifying the colour you want the link #' lines to be. Multiple formats supported (e.g. hexadecimal). #' @param nodeColour character string specifying the colour you want the node #' circles to be. Multiple formats supported (e.g. hexadecimal). #' @param textColour character string specifying the colour you want the text #' to be before they are clicked. Multiple formats supported (e.g. hexadecimal). #' @param opacity numeric value of the proportion opaque you would like the #' graph elements to be. #' @param diameter numeric diameter for the network in pixels. #' @param zoom logical, whether or not to enable the ability to use the mouse #' scroll-wheel to zoom in and out of the graph. #' @param parentElement character string specifying the parent element for the #' resulting svg network graph. This effectively allows the user to specify #' where on the html page the graph will be placed. By default the parent #' element is \code{body}. #' @param standAlone logical, whether or not to return a complete HTML document #' (with head and foot) or just the script. #' @param file a character string of the file name to save the resulting graph. #' If a file name is given a standalone webpage is created, i.e. with a header #' and footer. If \code{file = NULL} then result is returned to the console. #' @param iframe logical. If \code{iframe = TRUE} then the graph is saved to an #' external file in the working directory and an HTML \code{iframe} linking to #' the file is printed to the console. This is useful if you are using Slidify #' and many other HTML slideshow framworks and want to include the graph in the #' resulting page. If you set the knitr code chunk \code{results='asis'} then #' the graph will be rendered in the output. Usually, you can use #' \code{iframe = FALSE} if you are creating simple knitr Markdown or HTML #' pages. Note: you do not need to specify the file name if #' \code{iframe = TRUE}, however if you do, do not include the file path. #' @param d3Script a character string that allows you to specify the location of #' the d3.js script you would like to use. The default is #' \url{http://d3js.org/d3.v3.min.js}. #' #' #' @examples #' \dontrun{ #' # Download JSON data #' library(RCurl) #' URL <- "https://raw.github.com/christophergandrud/d3Network/master/JSONdata/flare.json" #' Flare <- getURL(URL) #' #' # Convert to list format #' Flare <- rjson::fromJSON(Flare) #' #' # Recreate Bostock example from http://bl.ocks.org/mbostock/4063570 #' d3ClusterDendro(List = Flare, #' file = "FlareCluster.html", zoom = TRUE, #' fontsize = 10, opacity = 0.9, #' widthCollapse = 0.8) #' } #' @source #' #' Mike Bostock \url{http://bl.ocks.org/mbostock/4063570}. #' #' @importFrom whisker whisker.render #' @importFrom rjson toJSON #' @export #' d3ClusterDendro <- function(List, height = 2200, width = 900, heightCollapse = 0, widthCollapse = 0.5, fontsize = 10, linkColour = "#ccc", nodeColour = "#3182bd", textColour = "#3182bd", opacity = 0.8, diameter = 980, zoom = FALSE, parentElement = "body", standAlone = TRUE, file = NULL, iframe = FALSE, d3Script = "http://d3js.org/d3.v3.min.js") { if (!isTRUE(standAlone) & isTRUE(iframe)){ stop("If iframe = TRUE then standAlone must be TRUE.") } # If no file name is specified create random name to avoid conflicts if (is.null(file) & isTRUE(iframe)){ Random <- paste0(sample(c(0:9, letters, LETTERS), 5, replace=TRUE), collapse = "") file <- paste0("NetworkGraph", Random, ".html") } # Create iframe dimensions larger than graph dimensions FrameHeight <- height + height * 0.07 FrameWidth <- width + width * 0.03 # Create mouseover font size fontsizeBig <- fontsize * 1.9 # Create link opacity at 50% of overall opacity linkOpacity <- opacity * 0.5 # Convert hierarchical list to JSON if (class(List) != "list"){ stop("List must be a list class object.") } RootList <- toJSON(List) RootList <- paste("var root =", RootList, "; \n") # Create webpage head PageHead <- BasicHead() # Create Style Sheet NetworkCSS <- whisker.render(TreeStyleSheet()) # Main scripts for creating the graph if (!isTRUE(zoom)){ MainScript1 <- whisker.render(MainClusterDendro1()) MainScript2 <- whisker.render(MainClusterDendro2()) } else if (isTRUE(zoom)){ MainScript1 <- whisker.render(ZoomClusterDendro1()) MainScript2 <- whisker.render(ZoomClusterDendro2()) } if (is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, MainScript1, RootList, MainScript2) } else if (is.null(file) & isTRUE(standAlone)){ cat(PageHead, NetworkCSS, MainScript1, RootList, MainScript2, "") } else if (!is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, MainScript1, RootList, MainScript2, file = file) } else if (!is.null(file) & !isTRUE(iframe)){ cat(PageHead, NetworkCSS, MainScript1, RootList, MainScript2, "", file = file) } else if (!is.null(file) & isTRUE(iframe)){ cat(PageHead, NetworkCSS, MainScript1, RootList, MainScript2, "", file = file) cat("", sep="") } } d3Network/R/d3Network.R0000644000176200001440000001416712463141360014347 0ustar liggesusers#' Function for creating simple D3 JavaScript force directed network graphs. #' DEPRICATED, USE d3SimpleNetwork #' #' \code{d3Network} creates D3 JavaScript force directed network graphs. NOTE: #' it is depricated. It is currently a direct copy of #' \code{\link{d3SimpleNetwork}} #' #' @param Data a data frame object with three columns. The first two are the #' names of the linked units. The third records an edge value. (Currently the #' third column doesn't affect the graph.) #' @param Source character string naming the network source variable in the #' data frame. If \code{Source = NULL} then the first column of the data frame #' is treated as the source. #' @param Target character string naming the network target variable in the #' data frame. If \code{Target = NULL} then the second column of the data frame #' is treated as the target. #' @param height numeric height for the network graph's frame area in pixels. #' @param width numeric width for the network graph's frame area in pixels. #' @param fontsize numeric font size in pixels for the node text labels. #' @param linkDistance numeric distance between the links in pixels (actually #' arbitrary relative to the diagram's size). #' @param charge numeric value indicating either the strength of the node #' repulsion (negative value) or attraction (positive value). #' @param linkColour character string specifying the colour you want the link #' lines to be. Multiple formats supported (e.g. hexadecimal). #' @param nodeColour character string specifying the colour you want the node #' circles to be. Multiple formats supported (e.g. hexadecimal). #' @param nodeClickColour character string specifying the colour you want the #' node circles to be when they are clicked. Also changes the colour of the #' text. Multiple formats supported (e.g. hexadecimal). #' @param textColour character string specifying the colour you want the text to #' be before they are clicked. Multiple formats supported (e.g. hexadecimal). #' @param opacity numeric value of the proportion opaque you would like the #' graph elements to be. #' @param parentElement character string specifying the parent element for the #' resulting svg network graph. This effectively allows the user to specify #' where on the html page the graph will be placed. By default the parent #' element is \code{body}. #' @param standAlone logical, whether or not to return a complete HTML document #' (with head and foot) or just the script. #' @param file a character string of the file name to save the resulting graph. #' If a file name is given a standalone webpage is created, i.e. with a header #' and footer. If \code{file = NULL} then result is returned to the console. #' @param iframe logical. If \code{iframe = TRUE} then the graph is saved to an #' external file in the working directory and an HTML \code{iframe} linking to #' the file is printed to the console. This is useful if you are using Slidify #' and many other HTML slideshow framworks and want to include the graph in the #' resulting page. If you set the knitr code chunk \code{results='asis'} then #' the graph will be rendered in the output. Usually, you can use #' \code{iframe = FALSE} if you are creating simple knitr Markdown or HTML #' pages. Note: you do not need to specify the file name if #' \code{iframe = TRUE}, however if you do, do not include the file path. #' @param d3Script a character string that allows you to specify the location of #' the d3.js script you would like to use. The default is #' \url{http://d3js.org/d3.v3.min.js}. #' #' @source #' D3.js was created by Michael Bostock. See \url{http://d3js.org/} and, #' more specifically for directed networks #' \url{https://github.com/mbostock/d3/wiki/Force-Layout} #' #' @importFrom whisker whisker.render #' #' @export d3Network <- function(Data, Source = NULL, Target = NULL, height = 600, width = 900, fontsize = 7, linkDistance = 50, charge = -200, linkColour = "#666", nodeColour = "#3182bd", nodeClickColour = "#E34A33", textColour = "#3182bd", opacity = 0.6, parentElement = "body", standAlone = TRUE, file = NULL, iframe = FALSE, d3Script = "http://d3js.org/d3.v3.min.js") { warning("NOTE: d3Network is depricated. Please use d3SimpleNetwork.", call. = FALSE) if (!isTRUE(standAlone) & isTRUE(iframe)){ stop("If iframe = TRUE then standAlone must be TRUE.") } # If no file name is specified create random name to avoid conflicts if (is.null(file) & isTRUE(iframe)){ Random <- paste0(sample(c(0:9, letters, LETTERS), 5, replace=TRUE), collapse="") file <- paste0("NetworkGraph", Random, ".html") } # Create iframe dimensions larger than graph dimensions FrameHeight <- height + height * 0.07 FrameWidth <- width + width * 0.03 # Create click text size clickTextSize <- fontsize * 2.5 # Subset data frame for network graph if (class(Data) != "data.frame"){ stop("Data must be a data frame class object.") } if (is.null(Source) & is.null(Target)){ NetData <- Data[, 1:2] } else if (!is.null(Source) & !is.null(Target)){ NetData <- data.frame(Data[, Source], Data[, Target]) } names(NetData) <- c("source", "target") # Convert data frame to JSON format LinkData <- toJSONarray(NetData) LinkData <- paste("var links =", LinkData, "; \n") # Create webpage head PageHead <- BasicHead() # Create Style Sheet NetworkCSS <- whisker.render(BasicStyleSheet()) # Main script for creating the graph MainScript <- whisker.render(BasicForceJS()) if (is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, LinkData, MainScript) } else if (is.null(file) & isTRUE(standAlone)){ cat(PageHead, NetworkCSS, LinkData, MainScript, "") } else if (!is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, LinkData, MainScript, file = file) } else if (!is.null(file) & !isTRUE(iframe)){ cat(PageHead, NetworkCSS, LinkData, MainScript, "", file = file) } else if (!is.null(file) & isTRUE(iframe)){ cat(PageHead, NetworkCSS, LinkData, MainScript, "", file = file) cat("", sep="") } } d3Network/R/d3ForceNetwork.R0000644000176200001440000001712712463141360015325 0ustar liggesusers#' Create a D3 JavaScript force directed network graph. #' #' @param Links a data frame object with the links between the nodes. It should #' include the \code{Source} and \code{Target} for each link. These should be #' numbered starting from 0. An optional \code{Value} variable can be included #' to specify how close the nodes are to one another. #' @param Nodes a data frame containing the node id and properties of the nodes. #' If no ID is specified then the nodes must be in the same order as the Source #' variable column in the \code{Links} data frame. Currently only a grouping #' variable is allowed. #' @param Source character string naming the network source variable in the #' \code{Links} data frame. #' @param Target character string naming the network target variable in the #' \code{Links} data frame. #' @param Value character string naming the variable in the \code{Links} data #' frame for how wide the links are. #' @param NodeID character string specifying the node IDs in the \code{Nodes} #' data frame. #' @param Group character string specifying the group of each node in the #' \code{Nodes} data frame. #' @param height numeric height for the network graph's frame area in pixels. #' @param width numeric width for the network graph's frame area in pixels. #' @param fontsize numeric font size in pixels for the node text labels. #' @param linkDistance numeric or character string. Either numberic fixed #' distance between the links in pixels (actually arbitrary relative to the #' diagram's size). Or a JavaScript function, possibly to weight by #' \code{Value}. For example: #' \code{linkDistance = "function(d){return d.value * 10}"}. #' @param linkWidth numeric or character string. Can be a numeric fixed width in #' pixels (arbitrary relative to the diagram's size). Or a JavaScript function, #' possibly to weight by \code{Value}. The default is #' \code{linkWidth = "function(d) { return Math.sqrt(d.value); }"}. #' @param charge numeric value indicating either the strength of the node #' repulsion (negative value) or attraction (positive value). #' @param linkColour character string specifying the colour you want the link #' lines to be. Multiple formats supported (e.g. hexadecimal). #' @param opacity numeric value of the proportion opaque you would like the #' graph elements to be. #' @param zoom logical, whether or not to enable the ability to use the mouse #' scroll-wheel to zoom in and out of the graph. #' @param parentElement character string specifying the parent element for the #' resulting svg network graph. This effectively allows the user to specify #' where on the html page the graph will be placed. By default the parent #' element is \code{body}. #' @param standAlone logical, whether or not to return a complete HTML document #' (with head and foot) or just the script. #' @param file a character string of the file name to save the resulting graph. #' If a file name is given a standalone webpage is created, i.e. with a header #' and footer. If \code{file = NULL} then result is returned to the console. #' @param iframe logical. If \code{iframe = TRUE} then the graph is saved to an #' external file in the working directory and an HTML \code{iframe} linking to #' the file is printed to the console. This is useful if you are using Slidify #' and many other HTML slideshow framworks and want to include the graph in the #' resulting page. If you set the knitr code chunk \code{results='asis'} then #' the graph will be rendered in the output. Usually, you can use #' \code{iframe = FALSE} if you are creating simple knitr Markdown or HTML pages. #' Note: you do not need to specify the file name if \code{iframe = TRUE}, #' however if you do, do not include the file path. #' @param d3Script a character string that allows you to specify the location of #' the d3.js script you would like to use. The default is #' \url{http://d3js.org/d3.v3.min.js}. #' #' @examples #' #### Tabular data example. #' # Load data #' data(MisLinks) #' data(MisNodes) #' #' # Create graph #' d3ForceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source", #' Target = "target", Value = "value", NodeID = "name", #' Group = "group", opacity = 0.4) #' #' \dontrun{ #' #### JSON Data Example #' # Load data JSON formated data into two R data frames #' library(RCurl) #' MisJson <- getURL("http://bit.ly/1cc3anB") #' MisLinks <- JSONtoDF(jsonStr = MisJson, array = "links") #' MisNodes <- JSONtoDF(jsonStr = MisJson, array = "nodes") #' #' # Create graph #' d3ForceNetwork(Links = MisLinks, Nodes = MisNodes, Source = "source", #' Target = "target", Value = "value", NodeID = "name", #' Group = "group", opacity = 0.4) #' } #' @source #' D3.js was created by Michael Bostock. See \url{http://d3js.org/} and, more #' specifically for force directed networks #' \url{https://github.com/mbostock/d3/wiki/Force-Layout}. #' #' @importFrom whisker whisker.render #' @export d3ForceNetwork <- function(Links, Nodes, Source, Target, Value = NULL, NodeID, Group, height = 600, width = 900, fontsize = 7, linkDistance = 50, linkWidth = "function(d) { return Math.sqrt(d.value); }", charge = -120, linkColour = "#666",opacity = 0.6, zoom = FALSE, parentElement = "body", standAlone = TRUE, file = NULL, iframe = FALSE, d3Script = "http://d3js.org/d3.v3.min.js") { if (!isTRUE(standAlone) & isTRUE(iframe)){ stop("If iframe = TRUE then standAlone must be TRUE.") } # If no file name is specified create random name to avoid conflicts if (is.null(file) & isTRUE(iframe)){ Random <- paste0(sample(c(0:9, letters, LETTERS), 5, replace=TRUE), collapse = "") file <- paste0("NetworkGraph", Random, ".html") } # Create iframe dimensions larger than graph dimensions FrameHeight <- height + height * 0.07 FrameWidth <- width + width * 0.03 # Create click text size clickTextSize <- fontsize * 2.5 # Subset data frames for network graph if (class(Links) != "data.frame"){ stop("Links must be a data frame class object.") } if (class(Nodes) != "data.frame"){ stop("Nodes must be a data frame class object.") } if (is.null(Value)){ LinksDF <- data.frame(Links[, Source], Links[, Target]) names(LinksDF) <- c("source", "target") } else if (!is.null(Value)){ LinksDF <- data.frame(Links[, Source], Links[, Target], Links[, Value]) names(LinksDF) <- c("source", "target", "value") } NodesDF <- data.frame(Nodes[, NodeID], Nodes[, Group]) names(NodesDF) <- c("name", "group") # Convert data frames to JSON format LinkData <- toJSONarray(LinksDF) LinkData <- paste("var links =", LinkData, "; \n") NodesData <- toJSONarray(NodesDF) NodesData <- paste("var nodes =", NodesData, "; \n") # Create webpage head PageHead <- BasicHead() # Create Style Sheet NetworkCSS <- whisker.render(ForceMainStyleSheet()) # Main script for creating the graph if (!isTRUE(zoom)){ MainScript <- whisker.render(MainForceJS()) } else if (isTRUE(zoom)){ MainScript <- whisker.render(ForceZoomJS()) } if (is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, LinkData, NodesData, MainScript) } else if (is.null(file) & isTRUE(standAlone)){ cat(PageHead, NetworkCSS, LinkData, NodesData, MainScript, "") } else if (!is.null(file) & !isTRUE(standAlone)){ cat(NetworkCSS, LinkData, NodesData, MainScript, file = file) } else if (!is.null(file) & !isTRUE(iframe)){ cat(PageHead, NetworkCSS, LinkData, NodesData, MainScript, "", file = file) } else if (!is.null(file) & isTRUE(iframe)){ cat(PageHead, NetworkCSS, LinkData, NodesData, MainScript, "", file = file) cat("", sep="") } } d3Network/R/templates.R0000644000176200001440000005146412463141360014466 0ustar liggesusers#' Basic HTML Header #' #' @keywords internals #' @noRd BasicHead <- function(){ " \n" } #' Mustache basic CSS template for d3Network #' #' @keywords internals #' @noRd BasicStyleSheet <- function(){ " \n" } #' Mustache basic Force Directed Network template for d3SimpleNetwork #' #' @keywords internals #' @noRd BasicForceJS <- function(){ "var nodes = {} // Compute the distinct nodes from the links. links.forEach(function(link) { link.source = nodes[link.source] || (nodes[link.source] = {name: link.source}); link.target = nodes[link.target] || (nodes[link.target] = {name: link.target}); link.value = +link.value; }); var width = {{width}} height = {{height}}; var force = d3.layout.force() .nodes(d3.values(nodes)) .links(links) .size([width, height]) .linkDistance({{linkDistance}}) .charge({{charge}}) .on(\"tick\", tick) .start(); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height); var link = svg.selectAll(\".link\") .data(force.links()) .enter().append(\"line\") .attr(\"class\", \"link\"); var node = svg.selectAll(\".node\") .data(force.nodes()) .enter().append(\"g\") .attr(\"class\", \"node\") .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout) .on(\"click\", click) .on(\"dblclick\", dblclick) .call(force.drag); node.append(\"circle\") .attr(\"r\", 8) .style(\"fill\", \"{{nodeColour}}\"); node.append(\"text\") .attr(\"x\", 12) .attr(\"dy\", \".35em\") .style(\"fill\", \"{{textColour}}\") .text(function(d) { return d.name; }); function tick() { link .attr(\"x1\", function(d) { return d.source.x; }) .attr(\"y1\", function(d) { return d.source.y; }) .attr(\"x2\", function(d) { return d.target.x; }) .attr(\"y2\", function(d) { return d.target.y; }); node.attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; }); } function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 16); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 8); } // action to take on mouse click function click() { d3.select(this).select(\"text\").transition() .duration(750) .attr(\"x\", 22) .style(\"stroke-width\", \".5px\") .style(\"opacity\", 1) .style(\"fill\", \"{{nodeClickColour}}\") .style(\"font\", \"{{clickTextSize}}px serif\"); d3.select(this).select(\"circle\").transition() .duration(750) .style(\"fill\", \"{{nodeClickColour}}\") .attr(\"r\", 16) } // action to take on mouse double click function dblclick() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 6) .style(\"fill\", \"{{nodeClickColour}}\"); d3.select(this).select(\"text\").transition() .duration(750) .attr(\"x\", 12) .style(\"stroke\", \"none\") .style(\"fill\", \"{{nodeClickColour}}\") .style(\"stroke\", \"none\") .style(\"opacity\", {{opacity}}) .style(\"font\", \"{{fontsize}}px serif\"); } \n" } #' Mustache main Force Directed Network template for d3ForceNetwork #' #' @keywords internals #' @noRd MainForceJS <- function(){ "var width = {{width}} height = {{height}}; var color = d3.scale.category20(); var force = d3.layout.force() .nodes(d3.values(nodes)) .links(links) .size([width, height]) .linkDistance({{linkDistance}}) .charge({{charge}}) .on(\"tick\", tick) .start(); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height); var link = svg.selectAll(\".link\") .data(force.links()) .enter().append(\"line\") .attr(\"class\", \"link\") .style(\"stroke-width\", {{linkWidth}}); var node = svg.selectAll(\".node\") .data(force.nodes()) .enter().append(\"g\") .attr(\"class\", \"node\") .style(\"fill\", function(d) { return color(d.group); }) .style(\"opacity\", {{opacity}}) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout) .call(force.drag); node.append(\"circle\") .attr(\"r\", 6) node.append(\"svg:text\") .attr(\"class\", \"nodetext\") .attr(\"dx\", 12) .attr(\"dy\", \".35em\") .text(function(d) { return d.name }); function tick() { link .attr(\"x1\", function(d) { return d.source.x; }) .attr(\"y1\", function(d) { return d.source.y; }) .attr(\"x2\", function(d) { return d.target.x; }) .attr(\"y2\", function(d) { return d.target.y; }); node.attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; }); } function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 16); d3.select(this).select(\"text\").transition() .duration(750) .attr(\"x\", 13) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{clickTextSize}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 8); } \n" } #' Mustache main Force Directed Network template for d3ForceNetwork with zooming capabilities. #' #' @keywords internals #' @noRd ForceZoomJS <- function(){ "var width = {{width}} height = {{height}}; var color = d3.scale.category20(); var force = d3.layout.force() .nodes(d3.values(nodes)) .links(links) .size([width, height]) .linkDistance({{linkDistance}}) .charge({{charge}}) .on(\"tick\", tick) .start(); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"pointer-events\", \"all\") .call(d3.behavior.zoom().on(\"zoom\", redraw)); var vis = svg .append(\"svg:g\"); vis.append(\"svg:rect\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"fill\", 'white'); function redraw() { vis.attr(\"transform\", \"translate(\" + d3.event.translate + \")\" + \" scale(\" + d3.event.scale + \")\"); } var link = vis.selectAll(\".link\") .data(force.links()) .enter().append(\"line\") .attr(\"class\", \"link\") .style(\"stroke-width\", {{linkWidth}}); var node = vis.selectAll(\".node\") .data(force.nodes()) .enter().append(\"g\") .attr(\"class\", \"node\") .style(\"fill\", function(d) { return color(d.group); }) .style(\"opacity\", {{opacity}}) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout) .call(force.drag); node.append(\"circle\") .attr(\"r\", 6) node.append(\"svg:text\") .attr(\"class\", \"nodetext\") .attr(\"dx\", 12) .attr(\"dy\", \".35em\") .text(function(d) { return d.name }); function tick() { link .attr(\"x1\", function(d) { return d.source.x; }) .attr(\"y1\", function(d) { return d.source.y; }) .attr(\"x2\", function(d) { return d.target.x; }) .attr(\"y2\", function(d) { return d.target.y; }); node.attr(\"transform\", function(d) { return \"translate(\" + d.x + \",\" + d.y + \")\"; }); } function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 16); d3.select(this).select(\"text\").transition() .duration(750) .attr(\"x\", 13) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{clickTextSize}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 8); } \n" } #' Mustache main (1) Reingold-Tilford Tree network graph template for d3Tree. #' #' @keywords internals #' @noRd MainRTTree1 <- function(){ "var width = {{width}} height = {{height}}; var diameter = {{diameter}}; var tree = d3.layout.tree() .size([360, diameter / 2 - 120]) .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; }); var diagonal = d3.svg.diagonal.radial() .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; }); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height) .append(\"g\") .attr(\"transform\", \"translate(\" + diameter / 2 + \",\" + diameter / 2 + \")\"); \n" } #' Mustache main (2) Reingold-Tilford Tree network graph template for d3Tree. #' #' @keywords internals #' @noRd MainRTTree2 <- function(){ "var nodes = tree.nodes(root), links = tree.links(nodes); var link = svg.selectAll(\".link\") .data(links) .enter().append(\"path\") .attr(\"class\", \"link\") .attr(\"d\", diagonal); var node = svg.selectAll(\".node\") .data(nodes) .enter().append(\"g\") .attr(\"class\", \"node\") .attr(\"transform\", function(d) { return \"rotate(\" + (d.x - 90) + \")translate(\" + d.y + \")\"; }) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout); node.append(\"circle\") .attr(\"r\", 4.5) .style(\"fill\", \"{{nodeColour}}\"); node.append(\"text\") .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"fill\", \"{{textColour}}\") .text(function(d) { return d.name; }); function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 9) d3.select(this).select(\"text\").transition() .duration(750) .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{fontsizeBig}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 4.5) d3.select(this).select(\"text\").transition() .duration(750) .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"font\", \"{{fontsize}}px serif\") .style(\"opacity\", {{opacity}}); } d3.select(self.frameElement).style(\"height\", diameter - 150 + \"px\"); \n" } #' Mustache Zooming (1) Reingold-Tilford Tree network graph template for d3Tree. #' #' @keywords internals #' @noRd ZoomRTTree1 <- function(){ "var width = {{width}} height = {{height}}; var diameter = {{diameter}}; var tree = d3.layout.tree() .size([360, diameter / 2 - 120]) .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; }); var diagonal = d3.svg.diagonal.radial() .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; }); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"pointer-events\", \"all\") .call(d3.behavior.zoom().on(\"zoom\", redraw)); var vis = svg .append(\"svg:g\"); vis.append(\"svg:rect\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"fill\", 'white'); function redraw() { vis.attr(\"transform\", \"translate(\" + d3.event.translate + \")\" + \" scale(\" + d3.event.scale + \")\"); } \n" } #' Mustache Zooming (2) Reingold-Tilford Tree network graph template for d3Tree. #' #' @keywords internals #' @noRd ZoomRTTree2 <- function(){ "var nodes = tree.nodes(root), links = tree.links(nodes); var link = vis.selectAll(\".link\") .data(links) .enter().append(\"path\") .attr(\"class\", \"link\") .attr(\"d\", diagonal); var node = vis.selectAll(\".node\") .data(nodes) .enter().append(\"g\") .attr(\"class\", \"node\") .attr(\"transform\", function(d) { return \"rotate(\" + (d.x - 90) + \")translate(\" + d.y + \")\"; }) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout) node.append(\"circle\") .attr(\"r\", 4.5) .style(\"fill\", \"{{nodeColour}}\"); node.append(\"svg:text\") .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"fill\", \"{{textColour}}\") .text(function(d) { return d.name; }); function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 9) d3.select(this).select(\"text\").transition() .duration(750) .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{fontsizeBig}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 4.5) d3.select(this).select(\"text\").transition() .duration(750) .attr(\"dy\", \".31em\") .attr(\"text-anchor\", function(d) { return d.x < 180 ? \"start\" : \"end\"; }) .attr(\"transform\", function(d) { return d.x < 180 ? \"translate(8)\" : \"rotate(180)translate(-8)\"; }) .style(\"font\", \"{{fontsize}}px serif\") .style(\"opacity\", {{opacity}}); } d3.select(self.frameElement).style(\"height\", diameter - 150 + \"px\"); \n" } #' Mustache Main (1) Cluster Dendrogram graphs template for d3Cluster. #' #' @keywords internals #' @noRd MainClusterDendro1 <- function(){ "var width = {{width}} height = {{height}}; var cluster = d3.layout.cluster() .size([height - height * {{heightCollapse}}, width - width * {{widthCollapse}}]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [d.y, d.x]; }); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height) .append(\"g\") .attr(\"transform\", \"translate(40,0)\"); \n" } #' Mustache Main (2) Cluster Dendrogram graphs template for d3Cluster. #' #' @keywords internals #' @noRd MainClusterDendro2 <- function(){ "var nodes = cluster.nodes(root), links = cluster.links(nodes); var link = svg.selectAll(\".link\") .data(links) .enter().append(\"path\") .attr(\"class\", \"link\") .attr(\"d\", diagonal); var node = svg.selectAll(\".node\") .data(nodes) .enter().append(\"g\") .attr(\"class\", \"node\") .attr(\"transform\", function(d) { return \"translate(\" + d.y + \",\" + d.x + \")\"; }) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout); node.append(\"circle\") .attr(\"r\", 4.5) .style(\"fill\", \"{{nodeColour}}\"); node.append(\"text\") .attr(\"dx\", function(d) { return d.children ? -8 : 8; }) .attr(\"dy\", 3) .style(\"text-anchor\", function(d) { return d.children ? \"end\" : \"start\"; }) .style(\"fill\", \"{{textColour}}\") .text(function(d) { return d.name; }); function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 9) d3.select(this).select(\"text\").transition() .duration(750) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{fontsizeBig}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 4.5) d3.select(this).select(\"text\").transition() .duration(750) .style(\"font\", \"{{fontsize}}px serif\") .style(\"opacity\", {{opacity}}); } d3.select(self.frameElement).style(\"height\", height + \"px\"); \n" } #' Mustache Zoom (1) Cluster Dendrogram graphs template for d3Cluster. #' #' @keywords internals #' @noRd ZoomClusterDendro1 <- function(){ "var width = {{width}} height = {{height}}; var cluster = d3.layout.cluster() .size([height - height * {{heightCollapse}}, width - width * {{widthCollapse}}]); var diagonal = d3.svg.diagonal() .projection(function(d) { return [d.y, d.x]; }); var svg = d3.select(\"{{parentElement}}\").append(\"svg\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"pointer-events\", \"all\") .call(d3.behavior.zoom().on(\"zoom\", redraw)); var vis = svg .append(\"svg:g\"); vis.append(\"svg:rect\") .attr(\"width\", width) .attr(\"height\", height) .attr(\"fill\", 'white'); function redraw() { vis.attr(\"transform\", \"translate(\" + d3.event.translate + \")\" + \" scale(\" + d3.event.scale + \")\"); } \n" } #' Mustache Zoom (2) Cluster Dendrogram graphs template for d3Cluster. #' #' @keywords internals #' @noRd ZoomClusterDendro2 <- function(){ "var nodes = cluster.nodes(root), links = cluster.links(nodes); var link = vis.selectAll(\".link\") .data(links) .enter().append(\"path\") .attr(\"class\", \"link\") .attr(\"d\", diagonal); var node = vis.selectAll(\".node\") .data(nodes) .enter().append(\"g\") .attr(\"class\", \"node\") .attr(\"transform\", function(d) { return \"translate(\" + d.y + \",\" + d.x + \")\"; }) .on(\"mouseover\", mouseover) .on(\"mouseout\", mouseout); node.append(\"circle\") .attr(\"r\", 4.5) .style(\"fill\", \"{{nodeColour}}\"); node.append(\"svg:text\") .attr(\"dx\", function(d) { return d.children ? -8 : 8; }) .attr(\"dy\", 3) .style(\"text-anchor\", function(d) { return d.children ? \"end\" : \"start\"; }) .style(\"fill\", \"{{textColour}}\") .text(function(d) { return d.name; }); function mouseover() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 9) d3.select(this).select(\"text\").transition() .duration(750) .style(\"stroke-width\", \".5px\") .style(\"font\", \"{{fontsizeBig}}px serif\") .style(\"opacity\", 1); } function mouseout() { d3.select(this).select(\"circle\").transition() .duration(750) .attr(\"r\", 4.5) d3.select(this).select(\"text\").transition() .duration(750) .style(\"font\", \"{{fontsize}}px serif\") .style(\"opacity\", {{opacity}}); } d3.select(self.frameElement).style(\"height\", height + \"px\"); \n" } #' Mustache for d3Sankey. #' #' @keywords internals #' @noRd SankeyJS <- function(){ "var margin = {top: 1, right: 1, bottom: 6, left: 1}, width = {{width}} - margin.left - margin.right, height = {{height}} - margin.top - margin.bottom; var formatNumber = d3.format(\",.0f\"), format = function(d) { return formatNumber(d); }, color = d3.scale.category20(); var svg = d3.select(\"{{parentElement}}\").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 + \")\"); var sankey = d3.sankey() .nodes(d3.values(nodes)) .links(links) .nodeWidth({{nodeWidth}}) .nodePadding({{nodePadding}}) .size([width, height]) .layout(32); var path = sankey.link(); var link = svg.append(\"g\").selectAll(\".link\") .data(sankey.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; }); link.append(\"title\") .text(function(d) { return d.source.name + \" \u2192 \" + d.target.name + \"\\n\" + format(d.value); }); var node = svg.append(\"g\").selectAll(\".node\") .data(sankey.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)); 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); }); 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\"); function dragmove(d) { d3.select(this).attr(\"transform\", \"translate(\" + d.x + \",\" + (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + \")\"); sankey.relayout(); link.attr(\"d\", path); } \n " } d3Network/R/plugins.R0000644000176200001440000001403712463141360014144 0ustar liggesusers#' D3 Sankey Plugin #' #' @source Michael Bostock. See #' \url{https://github.com/d3/d3-plugins/tree/master/sankey}. #' @keywords internals #' @noRd SankeyPlugin <- function(){ "