With the **DiagrammeR** package you can create, modify, analyze, and visualize network graph diagrams. The output can be incorporated into **RMarkdown** documents, integrated with **Shiny** web apps, converted to other graph formats, or exported as **PNG**, **PDF**, or **SVG** files.

Itâ€™s possible to make the above graph diagram using a combination of **DiagrammeR** functions strung together with the **magrittr** `%>%`

pipe:

```
library(DiagrammeR)
create_random_graph(
n = 140, m = 100,
directed = FALSE,
set_seed = 23) %>%
join_node_attrs(
df = get_s_connected_cmpts(.)) %>%
join_node_attrs(
df = get_degree_total(.)) %>%
colorize_node_attrs(
node_attr_from = sc_component,
node_attr_to = fillcolor,
alpha = 80) %>%
rescale_node_attrs(
node_attr_from = total_degree,
to_lower_bound = 0.2,
to_upper_bound = 1.5,
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()
```

**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 functionality 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 and specify styling attributes to differentiate nodes and edges by size, color, shape, opacity, length, and more.

Letâ€™s create a property graph that pertains to contributors to three software projects. This graph has nodes representing people and projects. The attributes `name`

, `age`

, `join_date`

, `email`

, `follower_count`

, `following_count`

, and `starred_count`

are specific to the `person`

nodes while the `project`

, `start_date`

, `stars`

, and `language`

attributes apply to the `project`

nodes. The edges represent the relationships between the people and the project.

The example graph file `repository.dgr`

is available in the `extdata/example_graphs_dgr/`

directory in the **DiagrammeR** package (currently, only for the **Github** version). We can load it into memory by using the `open_graph()`

function, with `system.file()`

to provide the location of the file within the package.

```
library(DiagrammeR)
# Load in a the small repository graph
graph <-
open_graph(
system.file(
"extdata/example_graphs_dgr/repository.dgr",
package = "DiagrammeR"))
```

We can always view the property graph with the `render_graph()`

function.

`render_graph(graph, layout = "kk")`

Now that the graph is set up, you can create queries with **magrittr** pipelines to get specific answers from the graph.

Get the average age of all the contributors. Select all nodes of type `person`

(not `project`

). Each node of that type has non-`NA`

`age`

attribute, so, get that attribute as a vector with `get_node_attrs_ws()`

and then calculate the mean with **R**â€™s `mean()`

function.

```
graph %>%
select_nodes(
conditions = type == "person") %>%
get_node_attrs_ws(
node_attr = age) %>%
mean()
#> [1] 33.6
```

We can get the total number of commits to all projects. We know that all edges contain the numerical `commits`

attribute, so, select all edges (`select_edges()`

by itself selects all edges in the graph). After that, get a numeric vector of `commits`

values and then get its `sum()`

(all commits to all projects).

```
graph %>%
select_edges() %>%
get_edge_attrs_ws(
edge_attr = commits) %>%
sum()
#> [1] 5182
```

Single out the one known as Josh and get his total number of commits as a maintainer and as a contributor. Start by selecting the Josh node with `select_nodes(conditions = name == "Josh")`

. In this graph, we know that all people have an edge to a project and that edge can be of the relationship (`rel`

) type of `contributor`

or `maintainer`

. We can migrate our selection from nodes to outbound edges with `trav_out_edges()`

(and we wonâ€™t provide a condition, just all the outgoing edges from Josh will be selected). Now we have a selection of 2 edges. Get that vector of `commits`

values with `get_edge_attrs_ws()`

and then calculate the `sum()`

. This is the total number of commits.

```
graph %>%
select_nodes(
conditions = name == "Josh") %>%
trav_out_edge() %>%
get_edge_attrs_ws(
edge_attr = commits) %>%
sum()
#> [1] 227
```

Get the total number of commits from Louisa, just from the maintainer role though. In this case weâ€™ll supply a condition in `trav_out_edge()`

. This acts as a filter for the traversal and this means that the selection will be applied to only those edges where the condition is met. Although there is only a single value, weâ€™ll still use `sum()`

after `get_edge_attrs_ws()`

(a good practice because we may not know the vector length, especially in big graphs).

```
graph %>%
select_nodes(
conditions = name == "Louisa") %>%
trav_out_edge(
conditions = rel == "maintainer") %>%
get_edge_attrs_ws(
edge_attr = commits) %>%
sum()
#> [1] 236
```

How do we do something more complex, like, get the names of people in graph above age 32? First, select all `person`

nodes with `select_nodes(conditions = type == "person")`

. Then, follow up with another `select_nodes()`

call specifying `age > 32`

. Importantly, have `set_op = "intersect"`

(giving us the intersection of both selections).

Now that we have the starting selection of nodes we want, we need to get all values of these nodesâ€™ `name`

attribute as a character vector. We do this with the `get_node_attrs_ws()`

function. After getting that vector, sort the names alphabetically with the **R** function `sort()`

. Because we get a named vector, we can use `unname()`

to not show us the names of each vector component.

```
graph %>%
select_nodes(
conditions = type == "person") %>%
select_nodes(
conditions = age > 32,
set_op = "intersect") %>%
get_node_attrs_ws(
node_attr = name) %>%
sort() %>%
unname()
#> [1] "Jack" "Jon" "Kim" "Roger" "Sheryl"
```

That **supercalc** project is progressing quite nicely. Letâ€™s get the total number of commits from all people to that most interesting project. Start by selecting that projectâ€™s node and work backwards. Traverse to the edges leading to it with `trav_in_edge()`

. Those edges are from committers and they all contain the `commits`

attribute with numerical values. Get a vector of `commits`

and then get the sum (there are `1676`

commits).

```
graph %>%
select_nodes(
conditions = project == "supercalc") %>%
trav_in_edge() %>%
get_edge_attrs_ws(
edge_attr = commits) %>%
sum()
#> [1] 1676
```

Kim is now a contributor to the **stringbuildeR** project and has made 15 new commits to that project. We can modify the graph to reflect this.

First, add an edge with `add_edge()`

. Note that `add_edge()`

usually relies on node IDs in `from`

and `to`

when creating the new edge. This is almost always inconvenient so we can instead use node labels (we know they are unique in this graph) to compose the edge, setting `use_labels = TRUE`

.

The `rel`

value in `add_edge()`

was set to `contributor`

â€“ in a property graph we always have values set for all node `type`

and edge `rel`

attributes. We will set another attribute for this edge (`commits`

) by first selecting the edge (it was the last edge made, so we can use `select_last_edges_created()`

), then, use `set_edge_attrs_ws()`

and provide the attribute/value pair. Finally, clear the active selections with `clear_selection()`

. The graph is now changed, have a look.

```
graph <-
graph %>%
add_edge(
from = "Kim",
to = "stringbuildeR",
rel = "contributor") %>%
select_last_edges_created() %>%
set_edge_attrs_ws(
edge_attr = commits,
value = 15) %>%
clear_selection()
render_graph(graph, layout = "kk")
```