Importing and visualizing network data
- Import network data from external edge list.
- Import node attributes from external dataset.
- Plot networks with
igraph
and with ggraph
.
- Plot with different network layouts.
# Packages
library(tidyverse)
library(igraph)
library(skimr)
library(janitor)
library(ggraph)
# Read the edgelist data into R
(elist <- read_csv("./Data/class_edgelist_clean.csv"))
## # A tibble: 44 × 3
## from to tie_weight
## <chr> <chr> <dbl>
## 1 David Sofia 2
## 2 David Maria 2
## 3 David Lem 1
## 4 David Beth 3
## 5 David Mark 1
## 6 David Amber 2
## 7 Sofia David 1
## 8 Sofia Maria 5
## 9 Sofia Beth 1
## 10 Sofia Amber 2
## # … with 34 more rows
# Using a function from igraph, convert the data frame above into a network.
graph <- graph_from_data_frame(elist)
# In igraph, networks are objects of class "igraph"
class(graph)
## [1] "igraph"
# Summary information about this network
graph
## IGRAPH 47248d4 DN-- 11 44 --
## + attr: name (v/c), tie_weight (e/n)
## + edges from 47248d4 (vertex names):
## [1] David->Sofia David->Maria David->Lem David->Beth David->Mark
## [6] David->Amber Sofia->David Sofia->Maria Sofia->Beth Sofia->Amber
## [11] Maria->David Maria->Sofia Maria->Lem Maria->Beth Maria->Amber
## [16] Jose ->Sofia Jose ->Maria Lem ->David Lem ->Maria Lem ->Jim
## [21] Lem ->Beth Lem ->Amber Jim ->Maria Jim ->Lem Jim ->Beth
## [26] Jim ->Amber Beth ->David Beth ->Sofia Beth ->Maria Beth ->Lem
## [31] Beth ->Jim Beth ->Amber Mark ->David Mark ->Jose Mark ->Amber
## [36] Kent ->Thomas Amber->David Amber->Sofia Amber->Maria Amber->Lem
## + ... omitted several edges
# The graph is Directed, Named, NOT Weighted, NOT Bipartite.
# The graph has 12 nodes and 144 edges.
# It has a vertex attribute called "name" and an edge attribute called
# "tie_weight".
# Plot the network
# Set the seed for reproducibility (more on this below)
set.seed(221)
# plot
plot(graph)

# The plot() function is extremely flexible. We can set vertex
# parameters (size, color etc.), edge parameters (width, color, line type etc.),
# label parameters (font, color, size), vertex layout, and more. See
# http://igraph.org/r/doc/plot.common.html for details.
# For example, let's plot with smaller arrows and labels for more clarity.
# Set the seed for reproducibility (more on this below).
set.seed(221)
# Plot
plot(graph, edge.arrow.size=0.5, vertex.label.cex=0.5)

# Let's now also import vertex attributes
(vert.attr <- read_csv("./Data/class_attributes.csv"))
## # A tibble: 12 × 4
## name age grade sex
## <chr> <dbl> <dbl> <chr>
## 1 Amber 23 70 F
## 2 Beth 35 85 F
## 3 David 22 100 M
## 4 Jim 26 95 M
## 5 Jose 30 90 M
## 6 Kent 23 75 M
## 7 Lem 32 95 M
## 8 Maria 25 80 F
## 9 Mark 24 80 M
## 10 Randy 26 100 M
## 11 Sofia 26 97 F
## 12 Thomas 23 92 M
# The same function we used above can import vertex attributes together with edge data.
graph <- graph_from_data_frame(d= elist, vertices= vert.attr)
# The igraph object now includes vertex attributes
graph
## IGRAPH 4ae9416 DN-- 12 44 --
## + attr: name (v/c), age (v/n), grade (v/n), sex (v/c), tie_weight (e/n)
## + edges from 4ae9416 (vertex names):
## [1] David->Sofia David->Maria David->Lem David->Beth David->Mark
## [6] David->Amber Sofia->David Sofia->Maria Sofia->Beth Sofia->Amber
## [11] Maria->David Maria->Sofia Maria->Lem Maria->Beth Maria->Amber
## [16] Jose ->Sofia Jose ->Maria Lem ->David Lem ->Maria Lem ->Jim
## [21] Lem ->Beth Lem ->Amber Jim ->Maria Jim ->Lem Jim ->Beth
## [26] Jim ->Amber Beth ->David Beth ->Sofia Beth ->Maria Beth ->Lem
## [31] Beth ->Jim Beth ->Amber Mark ->David Mark ->Jose Mark ->Amber
## [36] Kent ->Thomas Amber->David Amber->Sofia Amber->Maria Amber->Lem
## + ... omitted several edges
# Two ways to fix the network layout for visualization.
# 1) Set the same seed before each plot
set.seed(215)
plot(graph, edge.arrow.size=0.5)

# Plot again
set.seed(215)
plot(graph, edge.arrow.size=0.5)
# 2) Calculate network layout matrix separately, and always use that matrix for plot
set.seed(215)
layout.mat.fr <- layout_(graph=graph, layout=with_fr())
# Plot using that layout matrix
plot(graph, layout=layout.mat.fr, edge.arrow.size=0.5)
# Plot again
plot(graph, layout=layout.mat.fr, edge.arrow.size=0.5)
# Plot using different layout algorithms
# As star
set.seed(215)
layout.mat.st <- layout_(graph=graph, layout=as_star())
plot(graph, layout=layout.mat.st, edge.arrow.size=0.5)

# Kamada-kawai
set.seed(215)
layout.mat.kk <- layout_(graph=graph, layout=with_kk())
plot(graph, layout=layout.mat.kk, edge.arrow.size=0.5)

# You can use any matrix (with 2 columns and N rows, N being the number of
# vertices) for the graph layout, e.g. a matrix with spatial coordinates.
# More information on layout functions: http://igraph.org/r/doc/layout_.html
# A layout matrix can be set as the "default" layout matrix for a
# graph, by setting it as a graph attribute called "layout". If we do that,
# plot() will always (silently) use that matrix as graph's layout.
graph$layout <- layout.mat.kk
# Now we don't need to set the "layout" argument any more.
plot(graph, edge.arrow.size=0.5)
# To export the plot to an external file, use png() or pdf()
pdf("graph_kk.pdf")
plot(graph)
dev.off()
## quartz_off_screen
## 2
# Plot with ggraph and ggplot2 grammar
ggraph(graph) +
# Draw edges
geom_edge_link(
# Specify arrow size
arrow = arrow(length = unit(2, 'mm')),
# Distance between edge end and node
end_cap = circle(3, 'mm'),
# Distance between edge start and node
start_cap = circle(3, 'mm')) +
# Draw nodes
geom_node_point(color= "blue", fill = "lightblue", shape = 21, size=5) +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "black", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')

Network objects and attributes
- Vertex and edge attributes.
- Use vertex and edge attributes to analyze network composition.
- Use vertex and edge attributes to analyze network structure.
- Visualize characteristics of network composition and structure.
# Vertex sequence of the graph
V(graph)
## + 12/12 vertices, named, from 4ae9416:
## [1] Amber Beth David Jim Jose Kent Lem Maria Mark Randy
## [11] Sofia Thomas
# Edge sequence of the graph
E(graph)
## + 44/44 edges from 4ae9416 (vertex names):
## [1] David ->Sofia David ->Maria David ->Lem David ->Beth David ->Mark
## [6] David ->Amber Sofia ->David Sofia ->Maria Sofia ->Beth Sofia ->Amber
## [11] Maria ->David Maria ->Sofia Maria ->Lem Maria ->Beth Maria ->Amber
## [16] Jose ->Sofia Jose ->Maria Lem ->David Lem ->Maria Lem ->Jim
## [21] Lem ->Beth Lem ->Amber Jim ->Maria Jim ->Lem Jim ->Beth
## [26] Jim ->Amber Beth ->David Beth ->Sofia Beth ->Maria Beth ->Lem
## [31] Beth ->Jim Beth ->Amber Mark ->David Mark ->Jose Mark ->Amber
## [36] Kent ->Thomas Amber ->David Amber ->Sofia Amber ->Maria Amber ->Lem
## [41] Amber ->Jim Amber ->Beth Amber ->Mark Thomas->Kent
# Indexing based on vertex and edge attributes
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Extract vertex attribute
V(graph)$age
## [1] 23 35 22 26 30 23 32 25 24 26 26 23
# A vertex attribute is just a vector that we can re-use for any operation. For
# example: What's the average age in the network?
V(graph)$age %>%
mean
## [1] 26.25
# What's its standard deviation?
V(graph)$age %>%
sd
## [1] 4.048007
# Battery of descriptive stats using skimr functions
V(graph)$age %>%
skimr::skim()
Data summary
Name |
Piped data |
Number of rows |
12 |
Number of columns |
1 |
_______________________ |
|
Column type frequency: |
|
numeric |
1 |
________________________ |
|
Group variables |
None |
Variable type: numeric
data |
0 |
1 |
26.25 |
4.05 |
22 |
23 |
25.5 |
27 |
35 |
▇▆▁▃▂ |
# What's the distribution of gender in the network?
V(graph)$sex %>%
tabyl
## . n percent
## F 4 0.3333333
## M 8 0.6666667
# Vertex names are a vertex attribute created by default by graph_from_data_frame()
V(graph)$name
## [1] "Amber" "Beth" "David" "Jim" "Jose" "Kent" "Lem" "Maria"
## [9] "Mark" "Randy" "Sofia" "Thomas"
# Extract edge attribute
E(graph)$tie_weight
## [1] 2 2 1 3 1 2 1 5 1 2 2 5 1 2 4 1 1 2 2 5 2 2 1 5 5 2 4 3 1 1 5 3 1 1 1 3 2 3
## [39] 3 1 2 2 1 3
# Average tie weight (i.e., strength) in the network
E(graph)$tie_weight %>%
mean
## [1] 2.318182
# View female actors
V(graph)[sex=="F"]
## + 4/12 vertices, named, from 4ae9416:
## [1] Amber Beth Maria Sofia
# View strong ties
E(graph)[tie_weight > 2]
## + 15/44 edges from 4ae9416 (vertex names):
## [1] David ->Beth Sofia ->Maria Maria ->Sofia Maria ->Amber Lem ->Jim
## [6] Jim ->Lem Jim ->Beth Beth ->David Beth ->Sofia Beth ->Jim
## [11] Beth ->Amber Kent ->Thomas Amber ->Sofia Amber ->Maria Thomas->Kent
# View age of female actors
V(graph)[sex=="F"]$age
## [1] 23 35 25 26
# Mean age of female actors in the network
V(graph)[sex=="F"]$age %>%
mean
## [1] 27.25
# Display actor gender in graph visualization via ggraph
ggraph(graph) +
# Draw edges
geom_edge_link(arrow = arrow(length = unit(2, 'mm')),
end_cap = circle(3, 'mm'),
start_cap = circle(3, 'mm')) +
# Draw nodes
geom_node_point(aes(fill= sex), color = "blue", shape = 21, size=5) +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "darkblue", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')
## Using `stress` as default layout

# Alternative code to plot via igraph
# First plot with uniform blue color
plot(graph, vertex.color= "blue", edge.arrow.size=0.5,
vertex.label.cex=0.5, vertex.label.color= "white")

# The color can also be set as a vertex attribute in the graph itself, and the
# plot function will recognize it.
V(graph)$color <- "blue"
# Now the plot function recognizes the vertex attribute "color".
plot(graph, edge.arrow.size=0.5, vertex.label.cex=0.5, vertex.label.color= "white")

# Using indexing, set a different color for female actors
V(graph)[sex=="F"]$color
## [1] "blue" "blue" "blue" "blue"
V(graph)[sex=="F"]$color <- "red"
# Plot again
plot(graph, edge.arrow.size=0.5, vertex.label.cex=0.5, vertex.label.color= "white")

# Indexing based on network structure
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# View all actors who know Mark
V(graph)[nei("Mark")]
## + 3/12 vertices, named, from 4ae9416:
## [1] Amber David Jose
# View the age of all actors who know Mark.
V(graph)[nei("Mark")]$age
## [1] 23 22 30
# Average age in Mark's first-order neighborhood.
V(graph)[nei("Mark")]$age %>%
mean
## [1] 25
# View all edges that are incident on David
E(graph)[inc("David")]
## + 12/44 edges from 4ae9416 (vertex names):
## [1] David->Sofia David->Maria David->Lem David->Beth David->Mark
## [6] David->Amber Sofia->David Maria->David Lem ->David Beth ->David
## [11] Mark ->David Amber->David
# All edges "to" David
E(graph)[to("David")]
## + 6/44 edges from 4ae9416 (vertex names):
## [1] Sofia->David Maria->David Lem ->David Beth ->David Mark ->David
## [6] Amber->David
# View the strength of these edges
E(graph)[to("David")]$tie_weight
## [1] 1 2 2 4 1 2
# Average strength of all incoming edges to David
E(graph)[to("David")]$tie_weight %>%
mean
## [1] 2
# View all edges to David whose tie_weight is ==2
E(graph)[to("David") & tie_weight==2]
## + 3/44 edges from 4ae9416 (vertex names):
## [1] Maria->David Lem ->David Amber->David
# View all edges between women in the network.
# First get the vertex sequence of all women
women <- V(graph)[sex=="F"]
women
## + 4/12 vertices, named, from 4ae9416:
## [1] Amber Beth Maria Sofia
# Then get the edges among them.
E(graph)[women %--% women]
## + 12/44 edges from 4ae9416 (vertex names):
## [1] Sofia->Maria Sofia->Beth Sofia->Amber Maria->Sofia Maria->Beth
## [6] Maria->Amber Beth ->Sofia Beth ->Maria Beth ->Amber Amber->Sofia
## [11] Amber->Maria Amber->Beth
# Are there more edges among women or among men?
# Number of edges among women
E(graph)[women %--% women] %>% length
## [1] 12
# Number of edges among men
men <- V(graph)[sex=="M"]
E(graph)[men %--% men] %>% length
## [1] 9
# What is the strength of ties among women?
E(graph)[women %--% women]$tie_weight
## [1] 5 1 2 5 2 4 3 1 3 3 3 2
# Compare the distribution of tie strength among women vs among men
E(graph)[women %--% women]$tie_weight %>%
tabyl
## . n percent
## 1 2 0.16666667
## 2 3 0.25000000
## 3 4 0.33333333
## 4 1 0.08333333
## 5 2 0.16666667
E(graph)[men %--% men]$tie_weight %>%
tabyl
## . n percent
## 1 4 0.4444444
## 2 1 0.1111111
## 3 2 0.2222222
## 5 2 0.2222222
# Example of plot combining igraph and ggraph to highlight structural features
# of the network
# Create vertex attribute to flag nodes that are adjacent to Mark
V(graph)$nei.mark <- "No"
V(graph)[nei("Mark")]$nei.mark <- "Yes"
# Create edge attribute to flag edges that are incident on Mark
E(graph)$inc.mark <- "No"
E(graph)[inc("Mark")]$inc.mark <- "Yes"
# Create vertex attribute with vertex degree
V(graph)$degree <- degree(graph)
# Plot
ggraph(graph) +
# Draw edges
geom_edge_link(end_cap = circle(3, 'mm'),
start_cap = circle(3, 'mm'),
# For edge transparency
alpha = 0.7,
# Edge width as tie weight
aes(width = tie_weight,
# Edge color indicates if edge is incident on Mark
color = inc.mark)) +
# Draw nodes
geom_node_point(
# Node fill indicates whether node is adjacent to Mark
aes(fill= nei.mark,
# Node size is degree
size = degree),
shape= 21,
color = "blue") +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "darkblue", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')
## Using `stress` as default layout

Example of network measures: centrality
- Import network data from external adjacency matrix.
- Calculate and analyze centrality measures.
- Visualize centrality in network plots.
# Read in the campnet network adjacency matrix
campnet.adj <- read_csv(file="./Data/campnet_adj.csv") %>%
# Remove first column (node names, they're already stored as column names)
dplyr::select(-1) %>%
# Convert to matrix
as.matrix
## New names:
## * `` -> ...1
## Rows: 18 Columns: 19
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): ...1
## dbl (18): ANN, BERT, BILL, BRAZEY, CAROL, DON, GERY, HARRY, HOLLY, JENNIE, J...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Import into directed graph
camp <- graph_from_adjacency_matrix(campnet.adj,
mode="directed",
# To use matrix column names as "name" vertex attribute in igraph
add.colnames = NULL)
# Read in the vertex attributes
(campnet.attr <- read_csv(file="./Data/campattr.csv"))
## Rows: 18 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): id, Gender, Role
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## # A tibble: 18 × 3
## id Gender Role
## <chr> <chr> <chr>
## 1 ANN female student
## 2 BERT male prof
## 3 BILL male student
## 4 BRAZEY female student
## 5 CAROL female student
## 6 DON male student
## 7 GERY male prof
## 8 HARRY male student
## 9 HOLLY female student
## 10 JENNIE female student
## 11 JOHN male student
## 12 LEE male student
## 13 MICHAEL male student
## 14 PAM female student
## 15 PAT female student
## 16 PAULINE female student
## 17 RUSS male prof
## 18 STEVE male prof
# Note that actors in the graph are in the same order as actors in the attribute
# data frame.
V(camp)
## + 18/18 vertices, named, from 5a7c297:
## [1] ANN BERT BILL BRAZEY CAROL DON GERY HARRY HOLLY
## [10] JENNIE JOHN LEE MICHAEL PAM PAT PAULINE RUSS STEVE
campnet.attr$id
## [1] "ANN" "BERT" "BILL" "BRAZEY" "CAROL" "DON" "GERY"
## [8] "HARRY" "HOLLY" "JENNIE" "JOHN" "LEE" "MICHAEL" "PAM"
## [15] "PAT" "PAULINE" "RUSS" "STEVE"
# So we can simply set the columns from the attribute data frame as vertex
# attributes (because the order is the same, no merge is needed)
V(camp)$Gender <- campnet.attr$Gender
V(camp)$Role <- campnet.attr$Role
# Let's print the graph
camp
## IGRAPH 5a7c297 DN-- 18 54 --
## + attr: name (v/c), Gender (v/c), Role (v/c)
## + edges from 5a7c297 (vertex names):
## [1] ANN ->JENNIE ANN ->PAM ANN ->PAULINE BERT ->LEE
## [5] BERT ->RUSS BERT ->STEVE BILL ->DON BILL ->HARRY
## [9] BILL ->MICHAEL BRAZEY->BERT BRAZEY->LEE BRAZEY->STEVE
## [13] CAROL ->PAM CAROL ->PAT CAROL ->PAULINE DON ->HARRY
## [17] DON ->HOLLY DON ->MICHAEL GERY ->MICHAEL GERY ->RUSS
## [21] GERY ->STEVE HARRY ->DON HARRY ->HOLLY HARRY ->MICHAEL
## [25] HOLLY ->DON HOLLY ->PAM HOLLY ->PAT JENNIE->ANN
## [29] JENNIE->PAM JENNIE->PAT JOHN ->GERY JOHN ->PAULINE
## + ... omitted several edges
# Plot it.
# Calculate layout and set as layout attribute of graph.
set.seed(219)
camp$layout <- layout_(graph=camp, layout=with_kk())
# Plot the graph.
plot(camp, edge.arrow.size=0.1, vertex.label.cex=0.5)

# Calculate indegree
(camp.deg <- degree(camp, mode= "in"))
## ANN BERT BILL BRAZEY CAROL DON GERY HARRY HOLLY JENNIE
## 2 4 0 1 2 4 2 3 4 3
## JOHN LEE MICHAEL PAM PAT PAULINE RUSS STEVE
## 0 3 4 5 4 4 4 5
# Note that the result is simply a numeric vector
# It's a *named* numeric vector, where igraph vertex names are stored as
# vector names
names(camp.deg)
## [1] "ANN" "BERT" "BILL" "BRAZEY" "CAROL" "DON" "GERY"
## [8] "HARRY" "HOLLY" "JENNIE" "JOHN" "LEE" "MICHAEL" "PAM"
## [15] "PAT" "PAULINE" "RUSS" "STEVE"
# With tidyverse (enframe), we can convert this indegree vector to data frame
# and set the indegree variable name
camp.deg <- degree(camp, mode= "in") %>%
enframe(value = "indegree")
# View result
camp.deg
## # A tibble: 18 × 2
## name indegree
## <chr> <dbl>
## 1 ANN 2
## 2 BERT 4
## 3 BILL 0
## 4 BRAZEY 1
## 5 CAROL 2
## 6 DON 4
## 7 GERY 2
## 8 HARRY 3
## 9 HOLLY 4
## 10 JENNIE 3
## 11 JOHN 0
## 12 LEE 3
## 13 MICHAEL 4
## 14 PAM 5
## 15 PAT 4
## 16 PAULINE 4
## 17 RUSS 4
## 18 STEVE 5
# Betweenness, directed
camp.bet.dir <- betweenness(camp, directed = TRUE) %>%
enframe(value = "betw.dir")
# Betweenness, undirected
camp.bet.undir <- betweenness(camp, directed = FALSE) %>%
enframe(value = "betw.undir")
# Closeness, undirected
camp.clos.undir <- closeness(camp, mode="all") %>%
enframe(value = "clos.undir")
# Let's create a data frame with all centrality values.
# Start with degree data frame
camp.centr <- camp.deg %>%
# Join with directed betweenness data frame
left_join(camp.bet.dir, by = "name") %>%
# Join with undirected betweenness data frame
left_join(camp.bet.undir, by = "name") %>%
# Join with closeness data frame
left_join(camp.clos.undir, by = "name")
camp.centr
## # A tibble: 18 × 5
## name indegree betw.dir betw.undir clos.undir
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 ANN 2 0.5 1.78 0.0208
## 2 BERT 4 13.7 6.19 0.0196
## 3 BILL 0 0 0 0.02
## 4 BRAZEY 1 0 0 0.0169
## 5 CAROL 2 1.33 0.2 0.0208
## 6 DON 4 16.3 3.47 0.0233
## 7 GERY 2 54.7 35.9 0.0278
## 8 HARRY 3 2.33 1.74 0.0233
## 9 HOLLY 4 78.3 27.1 0.0263
## 10 JENNIE 3 6.33 1.2 0.0182
## 11 JOHN 0 0 33.1 0.0263
## 12 LEE 3 5 0 0.0169
## 13 MICHAEL 4 58.8 32.2 0.0278
## 14 PAM 5 32.5 15.1 0.0238
## 15 PAT 4 39.5 13.1 0.0233
## 16 PAULINE 4 12.5 33.5 0.025
## 17 RUSS 4 47.3 25.6 0.025
## 18 STEVE 5 16.8 23.8 0.0222
# Create histogram of degree centrality using ggplot2
ggplot(data= camp.centr, aes(x=indegree)) +
geom_histogram(binwidth = 1, color= "black")

# Plot network with nodes sized by centrality
# Create indegree attribute
V(camp)$indegree <- degree(camp, mode= "in")
# Plot
ggraph(camp) +
# Draw edges
geom_edge_link(end_cap = circle(3, 'mm'),
start_cap = circle(3, 'mm')) +
# Draw nodes
geom_node_point(
# Node fill indicates whether node is adjacent to Mark
aes(size = indegree),
shape= 21,
fill = "lightblue",
color = "blue") +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "darkblue", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')
## Using `stress` as default layout

# Same for betweenness: but now use both node size and color to visualize
# centrality
V(camp)$betw <- betweenness(camp, directed = FALSE)
# Plot
ggraph(camp) +
# Draw edges
geom_edge_link(end_cap = circle(3, 'mm'),
start_cap = circle(3, 'mm')) +
# Draw nodes
geom_node_point(
aes(size = betw, color = betw)) +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "darkblue", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')
## Using `stress` as default layout

# Plot with size = betweenness, color = role, shape = gender
ggraph(camp) +
# Draw edges
geom_edge_link(end_cap = circle(3, 'mm'),
start_cap = circle(3, 'mm')) +
# Draw nodes
geom_node_point(
# Node size, color, shape
aes(size = betw, color = Role, shape = Gender)) +
# Draw node labels (names)
geom_node_text(aes(label = name), color= "darkblue", size=3) +
# Theme details
theme_graph(base_family = 'Helvetica')
## Using `stress` as default layout
