# DiagrammeR Docs

Get an overview of DiagrammeR, learn the syntax, check out some examples.

Skip to main content

Get an overview of DiagrammeR, learn the syntax, check out some examples.

What's a graph library without the ability to modify the graph? The functions presented herein are all about changing the graph in specific ways. Whether it's adding a node here, an edge there, or deleting a whole swath of nodes, this sort of functionality is important.

The `add_node()`

and `add_edge()`

functions provide a facility for adding a single node or edge to an existing graph. Although you may prepare node data frames (*NDF*s) or edge data frames (*EDF*s) and incorporate those into a new graph object with the `create_graph()`

function, there may be new nodes or edges to add after creation of the graph object (say, as new data becomes available). After calling either of these functions, the new node or edge becomes part of the graph's internal *NDF* or *EDF*, respectively.

The `add_node()`

function allows one to add a single node to a graph. Specify the graph to which the node should be added and the node ID for the `node`

argument, and a node will be added. While the other arguments are optional, using just `graph`

and `node`

will result in the addition of an unconnected node. This might be desirable (say, if the graph is empty), but the more likely case is that edges to other nodes will be required upon addition of a new node. The `from`

and `to`

arguments (both optional) are where you would specify connections from existing nodes to the new node (with `to`

), and connections to existing nodes from the new node (with `from`

). A vector of node IDs can be supplied to either argument. The `label`

and `type`

arguments allow for direct setting of these node attributes during the addition of a node. Finally, a named vector of node attributes and their values can be included in the `add_node()`

call.

The `add_edge()`

function is meant for adding an edge between two extant graph nodes. Because the nodes must exist in the graph, this function cannot be invoked for an empty graph. (It can, however, be used for a graph with a single node since an edge can be created as a loop from and to the same node.) The basic means to add an edge to a graph with this function is to specify `from`

and `to`

nodes for the edge to be added. One can optionally add an edge `rel`

string as a value for the `rel`

argument.

```
###
# Add single nodes and edges
# with the `add_node()` and
# `add_edge()` functions
###
library(DiagrammeR)
library(magrittr)
# Create an empty graph
graph <- create_graph()
# Add two nodes, they will be
# given ID values that are
# monotonically increasing from `1`
graph <- add_node(graph)
graph <- add_node(graph)
# Get the node ID values
get_nodes(graph)
#> [1] "1" "2"
# Show the graph's internal NDF
get_node_df(graph)
#> nodes type label
#> 1 1 1
#> 2 2 2
# Create the same graph with
# magrittr `%>%` pipes
graph <-
create_graph() %>%
add_node %>%
add_node
# Show the graph's internal NDF
get_node_df(graph)
#> nodes type label
#> 1 1 1
#> 2 2 2
# Add an edge between the two nodes
graph <-
graph %>%
add_edge(1, 2)
# Show the graph's internal EDF
get_edge_df(graph)
#> from to rel
#> 1 1 2
```

So long as you are careful not to introduce nodes with duplicate ID values, you can add a node data frame (*NDF*) to existing graph. You can also add an edge data frame (*EDF*) to an existing graph. This can be done upon creation of the graph using the `create_graph()`

function, however, these it can be useful to add collections of nodes or edges as *NDF*s or *EDF*s, perhaps whenever new data is available for the graph.

```
###
# Add several nodes and
# edges to the graph in the
# form of NDFs and EDFs
###
library(DiagrammeR)
# Create an empty graph
graph <- create_graph()
# Create a node data frame
nodes <-
create_nodes(
nodes = 1:4,
type = "a",
color = c("red", "green",
"grey", "blue"),
value = c(3.5, 2.6, 9.4, 2.7))
# Add the node data frame to the
# graph object to create a graph
# with nodes
graph <-
add_node_df(graph = graph,
node_df = nodes)
get_node_df(graph)
#> nodes type label color value
#> 1 1 a 1 red 3.5
#> 2 2 a 2 green 2.6
#> 3 3 a 3 grey 9.4
#> 4 4 a 4 blue 2.7
# Create another node data frame
nodes_2 <-
create_nodes(
nodes = 5:8,
type = "b",
color = c("orange", "brown",
"aqua", "pink"),
value = c(1.6, 6.4, 0.8, 4.2))
# Add the second node data frame
# to the graph object to add more
# nodes with attributes to the
# graph
graph <-
add_node_df(
graph = graph,
node_df = nodes_2)
# Check the graph's internal
# NDF to see that the two NDFs
# were added
get_node_df(graph)
#> nodes type label color value
#> 1 1 a 1 red 3.5
#> 2 2 a 2 green 2.6
#> 3 3 a 3 grey 9.4
#> 4 4 a 4 blue 2.7
#> 5 5 b 5 orange 1.6
#> 6 6 b 6 brown 6.4
#> 7 7 b 7 aqua 0.8
#> 8 8 b 8 pink 4.2
# Create edges by first specifying
# `from` to `to` vectors of node
# ID values
from <-
c(1, 3, 5, 2, 3, 5, 2, 5, 3)
to <-
c(3, 6, 2, 7, 8, 7, 4, 4, 5)
# Create the EDF
edges <-
create_edges(
from = from,
to = to,
rel = "toward")
# Add the EDF to the graph
graph <-
add_edge_df(
graph,
edge_df = edges)
# Check the graph's internal
# EDF to see that the EDF
# was indeed added
get_edge_df(graph)
#> from to rel
#> 1 1 3 toward
#> 2 3 6 toward
#> 3 5 2 toward
#> 4 2 7 toward
#> 5 3 8 toward
#> 6 5 7 toward
#> 7 2 4 toward
#> 8 5 4 toward
#> 9 3 5 toward
# View the graph
render_graph(graph)
```

There may be times when the addition of many individual nodes or edges is desired. Add a multiple of new nodes to the graph in a single function call with the `add_n_nodes()`

function. Or, add several edges using a string representation with `add_edges_w_string()`

.

When adding nodes with `add_n_nodes()`

, the argument `n`

is for the number of new nodes to add to the graph, so, supply an integer that is greater than or equal to `1`

. Optionally, set node `type`

values for the new nodes (this is important for creating property graphs). The `set_node_type`

argument takes an optional string for applying a single `type`

attribute to all the newly created nodes.

```
###
# Add several nodes with different
# `type` attributes to the graph
# with the `add_n_nodes()`
# functions
###
library(DiagrammeR)
library(magrittr)
# Add 20 nodes to an empty graph
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(20) %>%
render_graph
# Add 20 nodes of 4 different types to
# an empty graph and then create edges
# between them
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(5, "A") %>%
add_n_nodes(5, "B") %>%
add_n_nodes(5, "C") %>%
add_n_nodes(5, "D") %>%
add_edge_df(create_edges(1:19, 2:20)) %>%
render_graph
```

The `add_edges_w_string()`

function provides an easy way to declare edges between nodes, provided that the node IDs are known in advance. The `edges`

argument is supplied with a string that defines edges between the nodes' IDs. If the graph is directed, then the format is `[ID]->[ID] [ID]->[ID] ...`

. If the graph is undirected then `->`

should be replaced by `--`

. The `rel`

argument provides an option to set a common edge `rel`

value for all the edges created (again, could be important for creating property graphs).

```
###
# Add several nodes of different
# types and add edges between the
# nodes with `add_edges_w_string()`
###
library(DiagrammeR)
library(magrittr)
# Add 12 nodes to an empty graph and
# then create edges between all nodes
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(4, "A") %>%
add_n_nodes(4, "B") %>%
add_n_nodes(4, "C") %>%
add_edges_w_string(
"1->6 2->10 5->8 9->2", "X") %>%
add_edges_w_string(
"3->7 6->2 11->5 12->2", "Y") %>%
add_edges_w_string(
"4->8 9->4 7->9 10->1", "Z") %>%
render_graph
```

Add a number of nodes to the graph by attaching them to or from a selection of nodes with `add_n_nodes_ws()`

. The nodes created can be assigned a common value for their `type`

attribute.

It's occasionally convenient to select one or more nodes and then add several nodes to or from them. Any use of `add_n_nodes_ws()`

requires a selection of one or more nodes in the graph (all functions ending with `_ws`

indicate the use of a node or edge selection). This selection of nodes can be made with a variety of node selection functions (e.g., `select_nodes()`

, `select_nodes_by_degree()`

, etc.) or through a traversal function (e.g., `trav_out`

, `trav_in_node`

, etc.). The direction in which edges travel is specified in the `direction`

argument. Using `from`

will direct the edges from the selected node(s) to the new nodes. With `from`

, edges will be made in the the opposite direction.

This function has `set_node_type`

and `set_edge_rel`

arguments, which allow you to optionally provide a common value for either the node `type`

or for the edge `rel`

type for all new nodes and edges created through this function call.

```
###
# Add several nodes with different
# `type` attributes to the graph
# with `add_n_nodes_ws()`
###
library(DiagrammeR)
library(magrittr)
# Create a graph with a central
# node and multiples of children nodes
create_graph(
graph_attrs = "output = visNetwork") %>%
add_node("A") %>%
select_nodes %>%
add_n_nodes_ws(3, "from", "B") %>%
clear_selection %>%
select_nodes("type", "B") %>%
add_n_nodes_ws(3, "from", "C") %>%
clear_selection %>%
select_nodes("type", "C") %>%
add_n_nodes_ws(3, "from", "D") %>%
render_graph
# Create a graph with two central
# nodes with a high indegree and
# outdegree
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(2, "A") %>%
add_edge(1, 2) %>%
select_nodes_by_id(1) %>%
add_n_nodes_ws(10, "to", "B") %>%
clear_selection %>%
select_nodes_by_id(2) %>%
add_n_nodes_ws(10, "from", "C") %>%
render_graph
# Create a graph in the same
# manner but add relationships
# and other attributes
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(1, "A") %>%
select_last_node %>%
set_node_attrs_ws("value", 5) %>%
add_n_nodes_ws(3, "to", "B", "toward") %>%
clear_selection %>%
select_nodes("type", "B") %>%
set_node_attrs_ws("value", 4) %>%
add_n_nodes_ws(3, "from", "C", "away") %>%
clear_selection %>%
select_nodes("type", "C") %>%
set_node_attrs_ws("value", 3) %>%
add_n_nodes_ws(5, "to", "D", "toward") %>%
select_nodes("type", "D") %>%
set_node_attrs_ws("value", 2) %>%
render_graph
```

```
```

Graphs can undergo all sorts of modifications, and this includes the removal of nodes or edges. The `delete_node()`

and `delete_edge()`

functions allow for the removal of single nodes or edges. Also, when deleting a node that has edges, those edge definitions will also be removed.

The function `delete_node()`

removes a single node from the graph. The functions expects a node ID value to uniquely identify the node to be deleted. As the function can only delete a single node per call, supply only a single node ID to the `node`

argument. All of the removed node's edges with other nodes in the graph will also be removed in this operation.

```
###
# Delete specific nodes
# from the graph using
# `delete_node()`
###
library(DiagrammeR)
library(magrittr)
# Create a graph with a central
# node and multiples of children nodes
graph <-
create_graph(graph_attrs =
"output = visNetwork") %>%
add_n_nodes(1, "A") %>%
select_nodes %>%
add_n_nodes_ws(3, "B") %>%
clear_selection %>%
select_nodes("type", "B") %>%
add_n_nodes_ws(3, "C")
# View the graph
graph %>% render_graph
# Remove the central node (`1`) by
# specifying the node ID directly
graph_delete_node_1 <-
graph %>% delete_node(1)
# View the modified graph
graph_delete_node_1 %>% render_graph
# Remove the first (and only) node
# with `type = A` from the graph
# (this is node `1`, as before)
graph_delete_node_2 <-
graph %>%
delete_node(
get_nodes(., "type", "A")[1])
# Inspect a list of nodes to
# ensure that node `1` has been
# removed
get_nodes(graph_delete_node_2)
#> [1] "2" "3" "4" "5" "6"
#> [6] "7" "8" "9" "10"
#> [10] "11" "12" "13"
# Also, edges were removed from
# this node removal; check that
# there are no edges from or to
# node `1`
graph_delete_node_2 %>%
get_edges %>%
{
from <- .[[1]]
to <- .[[2]]
nodes_in_edges <- c(from, to)
} %>% is_in(1, .)
#> [1] FALSE
```

The function `delete_edge()`

removes a single edge from the graph. Specify the graph object in `graph`

, the nodes in `from`

and `to`

, and the edge will removed if it exists.

```
###
# Delete specific edges
# from the graph using
# `delete_edge()`
###
library(DiagrammeR)
library(magrittr)
# Create a graph with a central
# node and multiples of children nodes;
# this is the same graph as in the
# previous example
graph <-
create_graph(
graph_attrs = "output = visNetwork") %>%
add_n_nodes(1, "A") %>%
select_nodes %>%
add_n_nodes_ws(3, "from", "B") %>%
clear_selection %>%
select_nodes("type", "B") %>%
add_n_nodes_ws(3, "from", "C")
# Remove the several edges by
# specifying the node ID values
# that make up those edges
graph_delete_edges <-
graph %>%
delete_edge(1, 2) %>%
delete_edge(1, 3) %>%
delete_edge(1, 4)
graph_delete_edges %>% render_graph
```

While the removal of several nodes or several edges can be performed with multiple statements using the `delete_node()`

and `delete_edge()`

functions, an often more desirable solution for greater removals is to create a selection of nodes or edges and delete the members with such selections. The latter strategy can be accomplished with the `delete_nodes_ws()`

and `delete_edges_ws()`

functions.

These functions only require a graph object with some selection of nodes or edges already set within the object. Recall that selections of nodes or edges can be made with a number of different functions (e.g., `select_nodes()`

, `select_edges()`

, `select_nodes_by_id()`

, `select_edges_by_node_id()`

, etc.). The following examples demonstrate how multiple nodes or edges can be removed by using a selection then invocation of either of these functions.

```
###
# Delete a number of nodes
# from the graph by making
# a selection and then using
# `delete_nodes_ws()`
###
library(DiagrammeR)
library(magrittr)
# Create a random graph with 150
# nodes and 180 edges
graph <-
create_random_graph(
150, 180,
directed = TRUE,
fully_connected = TRUE,
set_seed = 20) %>%
set_global_graph_attrs(
"graph", "output", "visNetwork")
# Set a random seed
set.seed(20)
# Randomly assign node `type` values
# of `1`, `2`, `3`, `4`, and `5` to
# each of the graph's nodes
for (i in 1:node_count(graph)) {
graph %<>%
node_type(
i, action = "add",
sample(1:5, 1))
}
# View this new graph; differently
# colored nodes are those with
# different `type` values
graph %>% render_graph
# A table of counts by node
# `type` can be displayed
graph %>% node_count(type = TRUE)
#> 5 4 2 3 1
#> 38 19 24 33 36
# Create a selection of nodes to
# mark them for deletion; first,
# select all nodes and delete all
# of them from the graph
graph_emptied <-
graph %>%
select_nodes %>%
delete_nodes_ws
# Ensure that the graph is empty
node_count(graph_emptied)
#> [1] 0
# Try a different type of
# selection that deletes all
# nodes corresponding to types
# `1` and `5`
graph_1_5_removed <-
graph %>%
select_nodes("type", 1) %>%
select_nodes("type", 5) %>%
delete_nodes_ws
graph_1_5_removed %>%
node_count(type = TRUE)
# Ensure that nodes of types
# `1` and `5` are no longer
# in the graph
graph_1_5_removed %>%
node_count(type = TRUE)
#> 4 2 3
#> 19 24 33
# View the modified graph, it
# looks a lot simpler now!
graph_1_5_removed %>%
render_graph
# Try yet another type of mass
# deletion where edges are retained
# on the basis nodes present with
# large numerical data values; free
# nodes are then also removed
graph_large_node_interactions <-
graph %>%
select_edges_by_node_id(
get_nodes(., "value", "<7")) %>%
delete_edges_ws %>%
clear_selection %>%
select_nodes_by_degree("both", 0) %>%
delete_nodes_ws
# View the revised graph
graph_large_node_interactions %>%
render_graph
```

`type`

AttributeThe `node_type()`

function provides several means to check the `type`

attribute for a node and perform different operations on that attribute. The different functionalities of `node_type`

can be changed through the use of these different keywords for the `action`

argument: `read`

, `check`

, `add`

, `update`

, and `delete`

. With `read`

set as the action, a node ID supplied with the graph object yields that node's `type`

attribute. Using `action = check`

with a node ID, you can check whether a `type`

attribute exists (it will return `TRUE`

or `FALSE`

. If the `type`

attribute hasn't been set for a node, you can add that using `action = add`

along with a string supplied for the `value`

argument. If a `type`

attribute has alredy been set for a node and you'd like to change it, use `action = update`

and include the updated string with the `value`

argument. Deleting a `type`

attribute for a node is easily accomplished by using `action = delete`

.

```
###
# Use the `node_type()`
# function to inspect and to
# make several modifications
# to a node's `type` value
###
library(DiagrammeR)
library(magrittr)
# Create a simple NDF
nodes <-
create_nodes(
nodes = 1:4,
type = c("1st", "2nd",
"3rd", "4th"))
# Create the graph object using
# the NDF
graph <-
create_graph(nodes_df = nodes)
# Read the node `type` attributes
graph %>% node_type(1, "read")
#> [1] "1st"
graph %>% node_type(2, "read")
#> [1] "2nd"
graph %>% node_type(3, "read")
#> [1] "3rd"
graph %>% node_type(4, "read")
#> [1] "4th"
# Get all the node types into
# a vector object
all_types <-
graph %>%
{
node_types <-
sapply(1:node_count(.),
function(x)
{node_type(., x,
"read")})
}
# What can you expect if the node
# ID provided doesn't match belong
# to any node in the graph? (An error.)
graph %>%
node_type(5, "read")
# --------------------------------------------------------
# Error in node_type(., 5, "read") :
# The specified node is not present in the graph.
# --------------------------------------------------------
# Remove a type assigned to node
# `4` using either of three
# keywords: `delete`, `remove`,
# or `drop`
graph %<>%
node_type(4, "delete")
# Now that node doesn't have a
# `type` value; it yields an
# NA when queried about that
graph %>%
node_type(4, "read")
#> [1] NA
# Add back the type assigned to
# node `4` using either of two
# keywords: `add` or `create`
graph %<>%
node_type(4, "add", "fourth")
# Add a node to the graph; the
# new node is added without a
# `type` value assigned
graph %<>% add_node
# Expect a value of FALSE when
# checking whether node `5` (just
# added) has a `type` value
# assigned
graph %>%
node_type(5, "check")
#> [1] FALSE
# When trying to remove a `type`
# for a node where no type value
# is set, there won't be an
# error, and, the graph won't
# change
graph_no_change_1 <-
graph %>%
node_type(5, "delete")
graph_no_change_1 %>%
node_type(5, "read")
#> [1] NA
# Attempt to add a `type` value
# for a node where a `type` value
# is already set; the value
# won't change (need to use the
# `update` mode)
graph_no_change_2 <-
graph %>%
node_type(1, "add", "first")
graph_no_change_2 %>%
node_type(1, "read")
#> [1] "1st"
# Using `update` results in the
# modification of the `type`
# value, for reals...
graph %<>%
node_type(1, "update", "first")
# ...but use `read` to be sure
graph %>%
node_type(1, "read")
#> [1] "first"
```

`rel`

AttributeThe `edge_rel()`

function is similar in principle and use to the `node_type()`

function. In this function, the edges' `rel`

attribute can be checked for existence, added, removed, or updated. As with the `node_type()`

function, this function uses the `action`

argument and performs various actions with these keywords: `read`

, `check`

, `add`

, `update`

, and `delete`

(same keywords as those for `node_type()`

). Using `read`

, supply node IDs for the `from`

and `to`

arguments. With that, you will receive the edge's currently set `rel`

attribute. The `rel`

attribute may or may not be set, so, using `action = check`

with a specified edge, the existence of the `rel`

attribute can be verified through a `TRUE`

or `FALSE`

return value. An unset `rel`

attribute for an edge can be set by using `action = add`

and a character string for the `value`

argument. To update an already set `rel`

attribute for an edge, use `action = update`

and provide the updated relationship string with the `value`

argument. Deleting a `rel`

attribute for an edge is done by using `action = delete`

with an edge.

```
###
# Use the `edge_rel()`
# function to inspect and to
# make several modifications
# to an edge's `rel` value
###
library(DiagrammeR)
library(magrittr)
# Create a simple NDF
nodes <-
create_nodes(
nodes = 1:4,
type = c("1st", "2nd",
"3rd", "4th"))
# Create a simple EDF
edges <-
create_edges(
from = c(1, 2, 3),
to = c(4, 3, 1),
rel = c("relates_to",
"did_with",
"relates_with"))
# Create the graph object using
# the NDF and the EDF
graph <-
create_graph(
nodes_df = nodes,
edges_df = edges)
# Using a `read` action on an
# edge with a relationship set
# will return the relationship
# label
graph %>%
edge_rel(1, 4, "read")
#> [1] "relates_to"
# Using a `read` action on an
# edge relationship for an
# edge that doesn't exist will
# throw an error
graph %>%
edge_rel(1, 2, "read")
# --------------------------------------------------------
# Error in edge_rel(., 1, 2, "read") :
# The specified edge is not present in the graph.
# --------------------------------------------------------
# Remove the edge rel across
# the `1`->`4` edge using the
# `delete` action (synonymous
# with `remove` and `drop`)
graph %<>%
edge_rel(1, 4, "delete")
# Check that the relationship
# value has been removed
# (FALSE value indidcates there
# is no `rel` set for this edge)
graph %>%
edge_rel(1, 4, "check")
#> [1] FALSE
# Using the `read` action will
# return an NA for the same
# reason
graph %>%
edge_rel(1, 4, "read")
#> [1] NA
# Attempting to remove the same
# edge `rel` value won't throw
# an error and the graph won't
# change
graph %<>%
edge_rel(1, 4, "delete")
# Add a new edge `rel` value
# across the `1`->`4` edge using
# the `add` action
graph %<>%
edge_rel(
1, 4, "add", "relates_to")
# If you'd like to change the
# `rel` value for the `1`->`4`
# edge, use the `update` action
# (`add` only works for those
# edges where `rel` is not set)
graph %<>%
edge_rel(
1, 4, "update", "did_with")
# Check that the `rel` value for
# the `1`->`4` edge has been set
graph %>%
edge_rel(1, 4, "read")
#> [1] "did_with"
```

A subgraph is a distinct graph composed of a subset of node and edges from another graph. Creating a subgraph in **DiagrammeR** is done by first creating a selection of nodes or edges and then invoking the `create_subgraph_ws()`

function.

The following example demonstrates how a selection of nodes based on their `type`

values (using `select_nodes()`

) and the subsequent creation of subgraphs can allow for a more focussed view of a larger graph.

```
###
# Create a graph, and create
# subgraphs based on both
# selections of nodes and
# selections of edges
###
library(DiagrammeR)
library(magrittr)
# Create a random graph with 120 nodes
# and 145 edges
graph <-
create_random_graph(
120, 145,
directed = TRUE,
fully_connected = TRUE,
set_seed = 20) %>%
set_global_graph_attrs(
"graph", "output", "visNetwork")
# Randomly assign node `type` values
# of `A`, `B`, `C`, and `D` to each
# of the graph's nodes
for (i in 1:node_count(graph)) {
graph %<>%
node_type(
i, action = "add",
sample(LETTERS[1:4], 1))
}
# View this new graph; differently
# colored nodes are those with different
# `type` values
graph %>% render_graph
# Create a subgraph solely with nodes
# where `type` is `A` and any edges
# are between nodes of the same type
subgraph_a_nodes <-
graph %>%
select_nodes("type", "A") %>%
create_subgraph_ws
# View the subgraph after coloring
# all nodes `lightgray`
subgraph_a_nodes %>%
select_nodes %>%
set_node_attrs_ws(
"color", "lightgray") %>%
render_graph
# Create subgraphs of all node types
# and place them into a graph series
subgraphs <-
create_series(series_name = "subgraphs")
for (i in 1:4) {
subgraphs <-
graph %>%
select_nodes("type", LETTERS[i]) %>%
create_subgraph_ws %>%
set_graph_name(LETTERS[i]) %>%
add_to_series(series_of_subgraphs)
}
# With `series_info()`, you can get basic
# info about which graphs are in the series
series_info(subgraphs)
#> graph name date_time tz nodes edges directed
#> 1 1 A <NA> <NA> 33 10 TRUE
#> 2 2 B <NA> <NA> 28 6 TRUE
#> 3 3 C <NA> <NA> 32 13 TRUE
#> 4 4 D <NA> <NA> 27 8 TRUE
# You can any of the subgraphs with the
# `render_graph_from_series()` function
render_graph_from_series(subgraphs, 1)
render_graph_from_series(subgraphs, 2)
render_graph_from_series(subgraphs, 3)
render_graph_from_series(subgraphs, 4)
```

Also possible is the creation of a subgraph based on a selection of edges.

```
###
# Create a graph, and create
# subgraphs based on both
# selections of nodes and
# selections of edges
###
library(DiagrammeR)
library(magrittr)
# Create the same random graph
# as in the previous example
# (120 nodes and 145 edges)
graph <-
create_random_graph(
120, 145,
directed = TRUE,
fully_connected = TRUE,
set_seed = 20) %>%
set_global_graph_attrs(
"graph", "output", "visNetwork")
# Randomly assign node `type` values
# of `A`, `B`, `C`, and `D` to each
# of the graph's nodes
for (i in 1:node_count(graph)) {
graph %<>%
node_type(
i, action = "add",
sample(LETTERS[1:4], 1))
}
# View the subgraph; the blue nodes
# those with `type` values of `A`
graph %>% render_graph
```

Setting the graph's name and time attributes can be useful when there is a collection of graphs and such properties can help when distinguishing the graph objects. The functions that deal with graph series objects can take advantage of any graph names and graph date-time values that are available. The `create_graph()`

function affords the option to set these parameters upon graph creation, however, the `set_graph_name()`

and `set_graph_time`

provide additional opportunities to add, modify, or remove such attributes.

The `set_graph_name()`

function takes a `graph`

object and a value for the `graph_name`

(this can be provided as `numeric`

value but will be coerced to a `character`

value. The same function can set a graph's name (changing from the default `NULL`

) and also modify a graph's name (replacing the value).

```
###
# Set the graph's name, then
# modify the name
###
library(DiagrammeR)
library(magrittr)
# Create an empty graph
graph <- create_graph()
# Set the graph's name
graph %<>% set_graph_name("nice_graph")
# Check the name of the graph
graph$graph_name
#> [1] "nice_graph"
# Change the graph's name
graph %<>% set_graph_name(1)
# Verify that the name has changed
graph$graph_name
#> [1] "1"
```

The `set_graph_time()`

function can be provided with a date or date-time string (for the `graph_time`

argument). This will be useful if the graph is to be inserted into a graph series of the `temporal`

type. An optional value for the time zone (tz) corresponding to the date or date-time string supplied as a value to `graph_time`

. If no time zone is provided then it will be implicitly set to GMT.

```
###
# Set the graph's date/time value,
# then modify the these properties
###
library(DiagrammeR)
library(magrittr)
# Create an empty graph
graph <- create_graph()
# Set the graph's time attribute with
# a well-formed date ("YYYY-MM-DD")
graph %<>% set_graph_time("2015-01-30")
# Check the `graph_time` attribute
graph$graph_time
#> [1] "2015-01-30"
# Note that since the time zone was
# not provided, the default is `GMT`
graph$graph_tz
#> [1] "GMT"
# I'll update the `graph_time`
# attribute with an actual
# timestamp (i.e., date + time) and
# a time zone
graph %<>%
set_graph_time(
"2015-01-30 15:26:54",
"Pacific/Pago_Pago")
# Let's check both the time and
# the time zone set for the graph
c(graph$graph_time,
graph$graph_tz)
#> [1] "2015-01-30 15:26:54"
#> [2] "Pacific/Pago_Pago"
```

```
```

Once a node or edge is in the graph, there are still opportunities to add or modify node or edge attribute values. There are four functions that help with this sort of task: `set_node_attrs()`

, `set_edge_attrs()`

, `set_node_attrs_ws()`

, and `set_edge_attrs_ws()`

.

When adding or modifying node attributes, you can target all the nodes at once (using `set_node_attrs()`

with no values provided to the `nodes`

argument). Specific nodes can be targeted by providing a vector of node ID values to the `nodes`

argument of the `set_node_attrs()`

function or by creating a selection of nodes (using `select_nodes()`

, `select_nodes_by_id()`

, `select_nodes_by_degree()`

, etc.) and using the `set_node_attrs_ws()`

function. Similarly, for additions or modifications of edge attributes, the `set_edge_attrs()`

and `set_edge_attrs_ws()`

are used in the same manner.

```
###
# Create a simple graph then
# set and modify several of
# the nodes' attributes
###
library(DiagrammeR)
library(magrittr)
# Create a random graph of
# 80 nodes, 140 edges
graph <-
create_random_graph(
80, 140,
directed = TRUE,
fully_connected = TRUE,
set_seed = 25) %>%
set_global_graph_attrs(
"graph", "output", "visNetwork")
# View the initial graph
graph %>% render_graph
# Create new node attributes and
# modify existing node attributes
graph_modified_node_attrs <-
graph %>%
set_node_attrs(
get_nodes(.), "type", "A") %>%
set_node_attrs(
c(1, 2, 3), "type", "B") %>%
set_node_attrs(
c(1, 2, 3), "value", 50) %>%
render_graph
# View the modified graph
graph_modified_node_attrs %>%
render_graph
```

Mainly for purposes of scaling data values to values supplied to aesthetics, the `rescale_node_attrs_ws()`

and `rescale_edge_attrs_ws()`

functions are available. Both allow for rescaling continuous numeric values to another set of numeric values or to a color range.

```
```