DiagrammeR
Graph and network visualization using tabular data in R
Install / Use
/learn @rich-iannone/DiagrammeRREADME
With the DiagrammeR package you can create, modify, analyze, and visualize network graph diagrams. The output can be incorporated into R Markdown documents, integrated with Shiny web apps, converted to other graph formats, or exported as image files.
<img src="man/figures/simple_graph.png">The graph above can be created with this combination of DiagrammeR functions:
example_graph <-
create_graph() %>%
add_pa_graph(
n = 50, m = 1,
set_seed = 23
) %>%
add_gnp_graph(
n = 50, p = 1/100,
set_seed = 23
) %>%
join_node_attrs(df = get_betweenness(.)) %>%
join_node_attrs(df = get_degree_total(.)) %>%
colorize_node_attrs(
node_attr_from = total_degree,
node_attr_to = fillcolor,
palette = "Greens",
alpha = 90
) %>%
rescale_node_attrs(
node_attr_from = betweenness,
to_lower_bound = 0.5,
to_upper_bound = 1.0,
node_attr_to = height
) %>%
select_nodes_by_id(nodes = get_articulation_points(.)) %>%
set_node_attrs_ws(node_attr = peripheries, value = 2) %>%
set_node_attrs_ws(node_attr = penwidth, value = 3) %>%
clear_selection() %>%
set_node_attr_to_display(attr = NULL)
render_graph(example_graph, layout = "nicely")
DiagrammeR’s graph functions allow you to create graph objects, modify those graphs, get information from the graphs, create a series of graphs, and do many other useful things. This makes it possible to generate a network graph with data available in tabular datasets. Two specialized data frames contain node data and attributes (node data frames) and edges with associated edge attributes (edge data frames). Because the attributes are always kept alongside the node and edge definitions (within the graph object itself), we can easily work with them.
Graph Basics
Let’s create a graph object with create_graph() and add some nodes and
edges to it. Each node gets a new integer ID upon creation. Each edge
also gets an ID starting from 1. The pipes between functions make the
whole process readable and understandable.
a_graph <-
create_graph() %>%
add_node() %>%
add_node() %>%
add_edge(from = 1, to = 2)
<img src="man/figures/a_graph.png">
We can take away an edge by using delete_edge().
b_graph <- a_graph %>% delete_edge(from = 1, to = 2)
<img src="man/figures/b_graph.png">
We can add a node to the graph while, at the same time, defining edges to or from existing nodes in the graph.
c_graph <- b_graph %>% add_node(from = 1, to = 2)
<img src="man/figures/c_graph.png">
Viewing the graph object in the console will provide some basic information about the graph and some pointers on where to get additional information.
c_graph
#> DiagrammeR Graph // 3 nodes / 2 edges
#> -- directed / connected / DAG / simple
#>
#> NODES / type: <unused> / label: <unused> info: `get_node_df()`
#> -- no additional node attributes
#> EDGES / rel: <unused> info: `get_edge_df()`
#> -- no additional edge attributes
#> SELECTION / <none>
#> CACHE / <none>
#> GLOBAL ATTRS / 17 are set info: `get_global_graph_attr_info()`
#> GRAPH ACTIONS / <none>
#> GRAPH LOG / <3 actions> -> add_edge() -> delete_edge() -> add_node()
Any time we add a node or edge to the graph, we can add node or edge
aesthetic or data attributes. These can be styling properties (e.g.,
color, shape), grouping labels (e.g., type and rel), or data
values that are useful for calculations and for display purposes. Most
node or edge creation functions (depending on whether they create either
edges, nodes, or both) have the arguments node_aes, edge_aes,
node_data, and edge_data. Using these, we can call the namesake
helper functions (node_aes(), edge_aes(), node_data(), and
edge_data()) to specifically target the created nodes or edges and
bind attribute data. An additional benefit in using the helper functions
(for the node/edge aesthetic attributes especially) is that RStudio can
provide inline help on attribute names and definitions when typing
node_aes( or edge_aes( and pressing the TAB key.
Here is an example of adding a node while setting its color,
fillcolor, and fontcolor node aesthetic attributes, and, adding an
edge with color, arrowhead, and tooltip edge aesthetic attributes.
In both the add_node() and the add_edge() calls, the new node and
edge were set with a value node/edge data attribute.
d_graph <-
c_graph %>%
add_node(
type = "type_a",
node_aes = node_aes(
color = "steelblue",
fillcolor = "lightblue",
fontcolor = "gray35"
),
node_data = node_data(
value = 2.5
)
) %>%
add_edge(
from = 1, to = 3,
rel = "interacted_with",
edge_aes = edge_aes(
color = "red",
arrowhead = "vee",
tooltip = "Red Arrow"
),
edge_data = edge_data(
value = 5.2
)
)
<img src="man/figures/d_graph.png">
Creating attributes and setting their values is often useful because we
can further work with the attributes (e.g., mutate values or even use
them during traversals). Furthermore, we can create aesthetic properties
based on numerical or categorical data. This is important for when you
want to display your graph diagram using the render_graph() function.
Don’t worry if attribute values weren’t set right during the creation of
the associated nodes or edges. They are ways to set attribute values for
existing nodes and edges. Functions are available for targeting the
specific nodes/edges (i.e., making a selection) and other functions
are used to set attribute values for the selected nodes or edges. Often,
this can be the more efficient strategy as we can target nodes/edges
based on their properties (e.g., degree, relationships to neighbors,
etc.). Here is an example where we select a node based on its value
attribute and modify its color node aesthetic attribute:
e_graph <-
d_graph %>%
select_nodes(conditions = value == 2.5) %>%
set_node_attrs_ws(node_attr = fillcolor, value = "orange") %>%
clear_selection()
To explain this a bit, we take the graph object d_graph, select only
the nodes that have a node value attribute of exactly 2.5. (We now
have an active node selection.) With the selected nodes, we set their
node attribute fillcolor with the value orange. Then we deactivate
the selection with clear_selection(). Now, if we view the graph with
render_graph() we get this:
There are quite a few functions that allow you to select nodes (e.g.,
select_nodes(), select_nodes_by_id(), select_last_nodes_created())
and edges (e.g., select_edges(), select_edges_by_edge_id(),
select_last_edges_created()). With these selections, we can apply
changes using functions that end with ..._ws() (with selection). As
seen, node attributes could be set/replaced with set_node_attrs_ws()
but we can also mutate attributes of selected nodes
(mutate_node_attrs_ws()), delete selected nodes (delete_nodes_ws()),
and even create a subgraph with that selection (create_subgraph_ws()).
Selections of nodes or edges can be inverted (where non-selected nodes
or edges become the active selection) with invert_selection(), certain
nodes/edges can be removed from the active selection with the
deselect_nodes()/deselect_edges(), and any selection can and should
be eventually cleared with clear_selection().
We can create a graph object and add graph primitives such as paths, cycles, and trees to it.
f_graph <-
create_graph() %>%
add_path(n = 3) %>%
add_cycle(n = 4) %>%
add_balanced_tree(k = 2, h = 2)
<img src="man/figures/f_graph.png">
You can add one or more randomly generated graphs to a graph object.
Here, let’s add a directed GNM graph with 10 nodes and 15 edges (the
set_seed option makes the random graph reproducible).
g_graph <-
create_graph() %>%
add_gnm_graph(
n = 15, m = 20,
set_seed = 23
)
<img src="man/figures/g_graph.png">
The undirected version of this graph is can be made using:
h_graph <-
create_graph(directed = FALSE) %>%
add_gnm_graph(
n = 15, m = 20,
set_seed = 23
)
<img src="man/figures/h_graph.png">
We can view the graph using render_graph(). There are several layouts
to choose from as well (e.g., nicely, tree, kk, fr, etc.).
render_graph(h_graph, layout = "fr")
<img src="man/figures/h_graph_2.png">
Using Data from Tables to Generate a Graph
The DiagrammeR package contains a few simple datasets that help illustrate how to create a graph with table data. The `
