--- title: "001 - Creating a Simple Graph" output: html_document --- **DiagrammeR** is all about making it easy to create, modify, and analyze graphs in an **R** environment. When just starting to use the package, it's useful to learn how to generate and view simple graphs. Here, we'll use just a few functions to generate node and edge data frames (i.e. graph building blocks), to create the graph object, and to view the graph. ## Setup Ensure that the development version of **DiagrammeR** is installed. Load in the package with `library()`. Additionally, load in the **tidyverse** packages. ```{r load_packages, message=FALSE, warning=FALSE, include=FALSE, results=FALSE} #devtools::install_github("rich-iannone/DiagrammeR") library(DiagrammeR) library(tidyverse) ``` ## Part 1. Creating a Simple Graph Using Data Frames For graph diagrams you need nodes and edges. Let's use the `create_node_df()` function to specify a collection of nodes and contain them in a data frame (a node data frame, or ndf). Immediately after that, inspect the node data frame. ```{r create_node_df} ndf <- create_node_df( n = 3, label = TRUE) ndf ``` The `n` argument is required here and it must indicate the number of nodes you intend this object to contain. The use of `label = TRUE` allows for copying of the node IDs as the node `label` (which is a node attribute). This is not always desirable, however. A better option is to specify a vector of text labels (you can use all manner of characters), but ensure that this vector is the same length as specified by `n`. If you ensure that the `label` node attribute always contains unique values, later on you can select individual nodes by `label` and perform actions on them. You may have noticed the node attribute `type` in the output. Values may optionally be provided for this such that the values are useful for categorizing collections of nodes. Let's refine the `ndf` object and include two different `type` values. ```{r create_ndf_type} ndf <- create_node_df( n = 3, type = c("A", "A", "B"), label = TRUE) ndf ``` Now onto the edges, those connections between the nodes. The edge connections are also collected in a data frame (this time, an edge data frame or edf). The `create_edge_df()` function is used to generate this object. ```{r create_edge_df} edf <- create_edge_df( from = c(1, 1), to = c(2, 3)) edf ``` The `from` and `to` arguments specify which nodes for the edge are outgoing and incoming, respectively. Here, the edges are: `1->2` and `1->3`. For directed graphs, the order is essential. The `rel` argument allows for inclusion of text labels in the same manner as the node `type`. This is useful for targeting specific groups of edges during a selection or traversal. Let's refine the `edf` object and include two different `rel` values. ```{r create_edf_rel} edf <- create_edge_df( from = c(1, 1), to = c(2, 3), rel = c("X", "Y")) edf ``` Now that we have an ndf and an edf, we can now combine those into a graph object. ```{r create_graph} the_graph <- create_graph( nodes_df = ndf, edges_df = edf) ``` Having a graph object is a great first step and you can do a lot with them (inspect, modify, join with other graph objects, etc.). Whenever you'd like to view the graph, use the `render_graph()` function. There are three renderers for graphs: ### Graphviz ```{r render_graph_graphviz} # Show the graph using the Graphviz engine render_graph(graph = the_graph, output = "graph") ``` ### visNetwork ```{r render_graph_visnetwork} # Show the graph using the visNetwork engine render_graph(graph = the_graph, output = "visNetwork") ``` ## Part 2. A Shortcut to the Same Graph You don't really need to have a node data frame in conjunction with the edge data frame to make a graph object. You can have both, either of them, or neither of them (creating an empty graph). Here is the empty graph case: ```{r create_graph_render} # Render a just created graph; there aren't # any nodes for the view should be empty render_graph( create_graph()) ``` ## Part 3. Graph with Nodes but No Edges We can just display nodes without edges by passing in just a node data frame to the `create_graph()` function. This a reasonable way to initialize a graph and edges between these initial nodes can always be added in later with functions like `add_edges()`, `add_edges_w_string()`, `add_edge_df()`, and `add_edges_from_table()`. ```{r create_graph_just_nodes} # Create the node data frame ndf <- create_node_df( n = 3, label = c("A", "B", "C")) # Use the `create_graph()` function the_graph <- create_graph(nodes_df = ndf) # View the graph render_graph(graph = the_graph) ``` Here is an example with 26 nodes, this time wrapping the `create_nodes()`, `create_graph()`, and `render_graph()` function calls into one big statement. We can provide exactly 26 capital letters as node labels by providing the built-in `LETTERS` vector to `label`. ```{r create_graph_nested_render} render_graph( create_graph( nodes_df = create_node_df( n = 26, label = LETTERS))) ``` Unicode characters can also be used as `label` attribute values: ```{r create_graph_nested_render_unicode} render_graph( create_graph( nodes_df = create_node_df( n = 3, label = c("α", "β", "γ")))) ``` Nesting calls like this becomes less readable with increasing numbers of operations. **DiagrammeR** works very well with the **magrittr** package to allow forward-piping of graph operations with the `%>%` operator. Here is the same set of functions as above, except using `%>%` to chain the operations left to right: ```{r create_graph_render_unicode_magrittr} create_node_df( n = 3, label = c("α", "β", "γ")) %>% create_graph(nodes_df = .) %>% render_graph() ``` The `.` character in the `create_graph()` statement indicates that the returned output from the previous `create_node_df()` statement should go here. Otherwise, the default behavior is that the output from a statement becomes the value for the first argument (which is often omitted entirely). The functions in **DiagrammeR** are designed to have this forward-pipe pattern work well. With further examples, you'll see how this can make even complicated graph operations easier to compose and to read.