|
| 1 | +--- |
| 2 | +title: "Networks with SNiGB" |
| 3 | +format: html |
| 4 | +--- |
| 5 | + |
| 6 | +Use this document as a starting point for practicing network analysis with the Social Network in Georgian Britain. |
| 7 | + |
| 8 | +```{r} |
| 9 | +#| label: setup |
| 10 | +#| message: false |
| 11 | +library(tidyverse) |
| 12 | +library(igraph) |
| 13 | +library(tidygraph) |
| 14 | +library(ggraph) |
| 15 | +library(here) |
| 16 | +``` |
| 17 | + |
| 18 | +## Create the network |
| 19 | +Load the data. We need an edge list and a node list. |
| 20 | + |
| 21 | +```{r} |
| 22 | +#| label: load-data |
| 23 | +edges <- read_csv(here("data-raw", "associations.csv")) |
| 24 | +individuals <- read_csv(here("data-raw", "individuals.csv")) |
| 25 | +``` |
| 26 | + |
| 27 | +```{r} |
| 28 | +#| label: look-at-data |
| 29 | +# Take a look at the data |
| 30 | +
|
| 31 | +``` |
| 32 | + |
| 33 | + |
| 34 | +Not all of the individuals are in the associates data, so let's find out who is in the associates data. Each person might be in either from `from` or the `to` column. The `unique()` function helps to find distinct names. |
| 35 | + |
| 36 | +```{r} |
| 37 | +#| label: nodes |
| 38 | +node_ids <- unique(c(edges$from, edges$to)) |
| 39 | +nodes <- individuals |> |
| 40 | + filter(id %in% node_ids) |
| 41 | +``` |
| 42 | + |
| 43 | +Now we are ready to use the edges and nodes to create a graph object. For whatever reason, I find that this works much better by creating a igraph object and then converting it to a tidygraph object later. |
| 44 | + |
| 45 | +```{r} |
| 46 | +#| label: create-graph |
| 47 | +assoc_graph <- graph_from_data_frame(d = edges, vertices = nodes, directed = FALSE) |
| 48 | +``` |
| 49 | + |
| 50 | +Look at the network you have created and find the 5 number summary as discussed in the [Networks with R](https://jessesadler.github.io/vt5444s26/resources/networks.html) resource page. |
| 51 | + |
| 52 | +```{r} |
| 53 | +#| label: 5-nr-summary |
| 54 | +# Investigate graph: 5 number summary |
| 55 | +# 1. Size |
| 56 | +
|
| 57 | +# 2. Density (0-1) |
| 58 | +
|
| 59 | +# 3. Components |
| 60 | +
|
| 61 | +# 4. Diameter |
| 62 | +
|
| 63 | +# 5. Clustering coefficient (0-1) |
| 64 | +
|
| 65 | +``` |
| 66 | + |
| 67 | +You will notice that the network has many different components; there are small clusters of connected people that are completely unconnected to the largest network. We can remove these eccentricities and concentrate on the large network with `largest_component()` from igraph. |
| 68 | + |
| 69 | +```{r} |
| 70 | +#| label: largest-component |
| 71 | +assoc_graph <- largest_component(assoc_graph) |
| 72 | +``` |
| 73 | + |
| 74 | +Now rerun the five-number summary on the new network. |
| 75 | + |
| 76 | +```{r} |
| 77 | +#| label: 5-nr-summary-comp |
| 78 | +# Investigate graph: 5 number summary |
| 79 | +# 1. Size |
| 80 | +
|
| 81 | +# 2. Density (0-1) |
| 82 | +
|
| 83 | +# 3. Components |
| 84 | +
|
| 85 | +# 4. Diameter |
| 86 | +
|
| 87 | +# 5. Clustering coefficient (0-1) |
| 88 | +
|
| 89 | +``` |
| 90 | + |
| 91 | + |
| 92 | +Let's also make a tidygraph object so we can see how these two interfaces differ. |
| 93 | + |
| 94 | +```{r} |
| 95 | +#| label: make-tidygraph |
| 96 | +assoc_tbl <- as_tbl_graph(assoc_graph) |
| 97 | +assoc_tbl |
| 98 | +``` |
| 99 | + |
| 100 | +`assoc_tbl` and `assoc_graph` are equivalent. They differ in how they represent the data. the tidygraph interface will be more familiar even if it consists of two data frames. One advantage is that it allows us to concentrate on either the nodes or edges data frame and plot aspects of one or the other with ggplot2. For instance, another way to get an overview of the nature of the network as a whole is to look at the distribution of the number of connections between nodes. It is typical in networks for many nodes to only have a few connections and for a small number of nodes to have a lot of connections. |
| 101 | + |
| 102 | +```{r} |
| 103 | +#| label: plot-degree |
| 104 | +assoc_tbl |> |
| 105 | + mutate(degree = centrality_degree()) |> # calculate number of connections |
| 106 | + as_tibble() |> # only get the nodes tibble |
| 107 | + ggplot(aes(x = degree)) + # Plot |
| 108 | + geom_histogram(bins = 20) + |
| 109 | + scale_x_log10() + # Use log scale for x axis |
| 110 | + theme_bw() |
| 111 | +``` |
| 112 | + |
| 113 | +There are many different [centrality measures](https://tidygraph.data-imaginist.com/reference/index.html#centrality) in tidygrapgh. Play around with different ones and see what they do. |
| 114 | + |
| 115 | +### Add id column |
| 116 | +You will notice that the tidygraph represents the nodes in the edge tibble as integers. It will make it easier to identify these values if the node tibble also has these values. The values are calculated in sequential order of the nodes, so we can redo this and add it as a column. |
| 117 | + |
| 118 | +```{r} |
| 119 | +#| label: add-id |
| 120 | +assoc_tbl <- assoc_tbl |> |
| 121 | + mutate(id = seq_along(assoc_tbl)) |> # Add id column from 1 to end of the tbl |
| 122 | + select(id, everything()) # Move the id column to the front |
| 123 | +``` |
| 124 | + |
| 125 | +Let's now look at a couple of different ways to explore connections in the graph. |
| 126 | + |
| 127 | +## Subgraphs |
| 128 | +You can create subgraphs using `filter()`. For instance, if you are interested in the connections between women in the data you might create a subgraph of women. |
| 129 | + |
| 130 | +```{r} |
| 131 | +#| label: subgraph |
| 132 | +female_graph <- assoc_tbl |> |
| 133 | + filter(sex == "female") |
| 134 | +female_graph |
| 135 | +``` |
| 136 | + |
| 137 | +You will notice that there are over 1,000 components, which tells us something about how men connect women together in this data. Explore this graph or create your own subgraph to investigate the data. |
| 138 | + |
| 139 | +## Ego graphs |
| 140 | +Neighborhoods or ego graphs provide a way to create a subgraph based on the connection to one or more node. Find an individual to investigate. You can search through `individuals` to find someone you might be interested in and do a filter for their name in `assoc_tbl`. One trick to do this is to use `str_starts()` within `filter()`. This lets you write the beginning of the name without having to write everything exactly perfectly. For instance: |
| 141 | + |
| 142 | +```{r} |
| 143 | +#| label: find-individual |
| 144 | +assoc_tbl |> |
| 145 | + filter(str_starts(name, "Jane Austen")) |
| 146 | +``` |
| 147 | + |
| 148 | +This shows the `id` for Jane Austen, which can be used to make the ego graph. |
| 149 | + |
| 150 | +```{r} |
| 151 | +#| label: austen-ego |
| 152 | +to_local_neighborhood(assoc_tbl, node = 1) |
| 153 | +``` |
| 154 | + |
| 155 | +Within tidygraph, this creates a temporary representation of the graph. Notice the `$neighborhood` at the beginning of the print out of the object. This is because `to_local_neighborhood()` actually returns a list. Run `class(to_local_neighborhood(assoc_tbl, node = 1))` to confirm this. If you want to actually create a new tidygraph object, you need to use `convert()` in the following manner: |
| 156 | + |
| 157 | +```{r} |
| 158 | +#| label: tidy-convert |
| 159 | +ja_ego <- convert(assoc_tbl, to_local_neighborhood, node = 7550) |
| 160 | +``` |
| 161 | + |
| 162 | +See the [documentation](https://tidygraph.data-imaginist.com/reference/morph.html) for a fuller explanation of this. |
| 163 | + |
| 164 | +You can now plot with either the igraph version of `plot()` of using ggraph. Here is the basic plot. |
| 165 | + |
| 166 | +```{r} |
| 167 | +#| label: base-ego-plot |
| 168 | +plot(ja_ego) |
| 169 | +``` |
| 170 | + |
| 171 | +Try to create a plot with ggraph following the instructions in [visualize the graph](https://jessesadler.github.io/vt5444s26/resources/networks.html#visualize-the-graph). |
| 172 | + |
| 173 | +```{r} |
| 174 | +#| label: ego-ggraph |
| 175 | +
|
| 176 | +``` |
| 177 | + |
| 178 | +## Conclusion |
| 179 | +There are many other ways to explore this network data. Make sure to look through the [igraph](https://r.igraph.org/index.html) and [tidygraph](https://tidygraph.data-imaginist.com/index.html) documentation for ideas. |
0 commit comments