knitr::opts_chunk$set( collapse = TRUE, echo = TRUE, warning = FALSE, message = FALSE, fig.width = 8, comment = "#>" ) library(dplyr) library(jsonlite)
library(cytoscape) nodes <- data.frame(id = c('a','b')) edges <- data.frame(id = 'ab', source = 'a', target = 'b') cytoscape(nodes = nodes, edges = edges)
Nodes and edges can all be styled using CSS.
ct <- cytoscape(nodes = nodes, edges = edges) ct %>% node_style('background-color' = '#ff0000')
ct %>% edge_style('line-color' = '#ff0000')
Every network chart requires two data.frames
one for the nodes and another for the edges. Often you will already have a data.frame
with the edge, or source
, target
. In the example below we have a data.frame
of Comtrade waste plastic exports for December 2017 where the source counrty and the destination country are deliniated. These fields need to be renamed to source
and target
for cytoscape
to use it. For the nodes
data.frame
you need to create an id
field that contains all of the unique values found in the source
and target
fields of the edges
data.frame
.
df <- cytoscape::comtrade edges <- df %>% dplyr::select(source = reporter, target = partner) %>% dplyr::mutate(id = paste(source, '_', target)) nodes <- data.frame(id = unique(c(edges$source, edges$target)), stringsAsFactors = FALSE) cytoscape(nodes = nodes, edges = edges) %>% layout('grid', rows = 4)
# cytoscape(nodes = nodes, edges = edges) %>% # layout('breadthfirst', directed = TRUE)
You can use coordinates to fix the location of nodes. But the package is not spatially enabled and does not check or transform the coordinates you pass.
coords <- cytoscape::coords %>% rename(x = lon, y = lat) %>% filter(id != 'World') %>% mutate(y = -y) # this will depend on coordinates used edges <- filter(edges, source %in% coords$id, target %in% coords$id) cytoscape(nodes = coords, edges = edges) %>% layout('preset') %>% node_style(width = 3, height = 3, 'font-size' = 8) %>% edge_style(width = 1)
Replicate the Cytograph.js
images example. This example does not currently include the touch effects.
img_nodes <- data.frame(id = c('cat','bird','ladybug','aphid','rose','grasshopper','plant','wheat'), images = c('https://farm2.staticflickr.com/1261/1413379559_412a540d29_b.jpg', 'https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg', 'https://farm4.staticflickr.com/3063/2751740612_af11fb090b_b.jpg', 'https://farm9.staticflickr.com/8316/8003798443_32d01257c8_b.jpg', 'https://farm6.staticflickr.com/5109/5817854163_eaccd688f5_b.jpg', 'https://farm7.staticflickr.com/6098/6224655456_f4c3c98589_b.jpg', 'https://farm1.staticflickr.com/231/524893064_f49a4d1d10_z.jpg', 'https://farm3.staticflickr.com/2660/3715569167_7e978e8319_b.jpg'), stringsAsFactors = FALSE) img_edges <- data.frame(source = c('cat','bird','bird','grasshopper','grasshopper','ladybug','aphid'), target = c('bird','ladybug','grasshopper','plant','wheat','aphid','rose'), stringsAsFactors = FALSE) cytoscape(nodes = img_nodes, edges = img_edges) %>% layout(name = 'breadthfirst', directed = TRUE, padding = 10) %>% node_style('height' = 80, 'width' = 80, 'background-fit' = 'cover', 'border-color' = '#000', 'border-width' = 3, 'border-opacity' = 0.5, 'label' = NULL) %>% edge_style('curve-style' = 'bezier', 'width' = 6, 'target-arrow-shape' = 'triangle', 'line-color' = '#ffaaaa', 'target-arrow-color' = '#ffaaaa') %>% node_images()
Since cytoscape
version 3.3.0 it has been possible to include background gradients in node styles. This is included in this package as of version 0.0.2.
cytoscape(nodes = img_nodes, edges = img_edges) %>% layout(name = 'breadthfirst', directed = TRUE, padding = 10) %>% node_style("content" = "data(id)", "text-valign" = "center", "text-halign" = "center", 'height' = 80, 'width' = 80, "background-fill" = "radial-gradient", 'background-fit' = 'cover', "background-gradient-stop-colors" = "cyan magenta yellow", "background-gradient-stop-positions" = "25 75 80" )
Compound graphs where nodes are grouped are also possible. Add parent
and node_color
columns to the nodes data.frame
. The final step is to add nodes for each of the groups, note the bind_rows()
function in the example below. Thanks to gilhornung for this example.
df <- cytoscape::comtrade gp_nodes <- tibble(id = unique(c(df$reporter, df$partner))) %>% # Define node groups mutate(parent = ifelse(id %in% c("Nigeria", "Kenya", "South Africa"), "Africa", "Not Africa")) %>% # Define node colors mutate(node_color = ifelse(parent == "Africa", "forestgreen", "darkorange")) %>% # Need to add the nodes for the two groups, Africa and "Not Africa" bind_rows(data_frame(id = c("Africa", "Not Africa"), node_color="whitesmoke")) gp_edges <- df %>% dplyr::select(source = reporter, target = partner) %>% dplyr::mutate(id = paste0(source, '-', target)) cytoscape(nodes = gp_nodes, edges = gp_edges) %>% node_style('background-color' = 'data(node_color)') %>% cola_layout(avoidOverlap = T)
Constraint based layouts provided through (cola.js) can be used via the cytoscape-cola plugin. All options available in the plugin API are available but have not yet been tested.
cytoscape(nodes = nodes, edges = edges) %>% cola_layout()
To use the Cola alignment
variable you need to pass a javascript object or function. You can do this using htmltools::JS()
.
aln_nodes <- data.frame(id = c('cat','bird','ladybug','grasshopper','wheat'), stringsAsFactors = FALSE) aln_edges <- data.frame(source = c('cat', 'bird', 'bird', 'grasshopper'), target = c('bird','ladybug','grasshopper','wheat' ), stringsAsFactors = FALSE) opts = htmlwidgets::JS('function( node ){ ', 'console.log(node._private.data.id);', 'if (node._private.data.id === "cat") {return { x: 0} }', 'else if (node._private.data.id === "bird") {return { x: 0, y: 0 } }', 'else if (node._private.data.id === "ladybug") {return { x: 0} }', 'else if (node._private.data.id === "wheat") {return {y: 0 } }', 'else if (node._private.data.id === "grasshopper") {return {y: 0 } }', '}') cytoscape(nodes = aln_nodes, edges = aln_edges) %>% cola_layout(alignment = opts)
A minimal shiny example can be run from the cytoscape
package of from inst/shiny/minimum_shiny
shiny::runApp(system.file('shiny/minimum_shiny', package = 'cytoscape'))
If you already have a complete JSON
this can be passed through directly as a character string. The JSON
character is parsed in javascript
using JSON.parse()
so it is good practice to first test your JSON
is properly formed. On the R
side you can use jsonlite::fromJSON()
or the web-service http://json.parser.online.fr/ can sometimes give more meaningfull error messages.
json <- '{ "elements":[ { "data": { "id": "a" } }, { "data": { "id": "b" } }, { "data": { "id": "ab", "source": "a", "target": "b" } } ], "style": [ { "selector": "node", "style": { "background-color": "#666", "label": "data(id)" } }, { "selector": "edge", "style": { "width": 3, "line-color": "#ccc", "target-arrow-color": "#ccc", "target-arrow-shape": "triangle" } } ], "layout": { "name": "grid", "rows": 1 } }' cytoscape(json = json)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.