1.0 Installing Packages

packages = c('igraph', 'tidygraph', 'ggraph', 'visNetwork', 'lubridate', 'tidyverse')

for(p in packages){library
  if(!require(p, character.only = T)){
    install.packages(p)
  }
  library(p, character.only = T)
}
## Loading required package: igraph
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
## Loading required package: tidygraph
## 
## Attaching package: 'tidygraph'
## The following object is masked from 'package:igraph':
## 
##     groups
## The following object is masked from 'package:stats':
## 
##     filter
## Loading required package: ggraph
## Loading required package: ggplot2
## Loading required package: visNetwork
## Loading required package: lubridate
## 
## Attaching package: 'lubridate'
## The following object is masked from 'package:igraph':
## 
##     %--%
## The following object is masked from 'package:base':
## 
##     date
## Loading required package: tidyverse
## -- Attaching packages ---------------------------------------------------------------------------------------------------------------------- tidyverse 1.2.1 --
## v tibble  2.1.3     v purrr   0.3.2
## v tidyr   1.0.0     v dplyr   0.8.3
## v readr   1.3.1     v stringr 1.4.0
## v tibble  2.1.3     v forcats 0.4.0
## -- Conflicts ------------------------------------------------------------------------------------------------------------------------- tidyverse_conflicts() --
## x lubridate::%--%()        masks igraph::%--%()
## x lubridate::as.difftime() masks base::as.difftime()
## x dplyr::as_data_frame()   masks tibble::as_data_frame(), igraph::as_data_frame()
## x purrr::compose()         masks igraph::compose()
## x tidyr::crossing()        masks igraph::crossing()
## x lubridate::date()        masks base::date()
## x dplyr::filter()          masks tidygraph::filter(), stats::filter()
## x dplyr::groups()          masks tidygraph::groups(), igraph::groups()
## x lubridate::intersect()   masks base::intersect()
## x dplyr::lag()             masks stats::lag()
## x lubridate::setdiff()     masks base::setdiff()
## x purrr::simplify()        masks igraph::simplify()
## x lubridate::union()       masks igraph::union(), base::union()

1.1 Data Wrangling

GAStech_nodes <- read_csv("data/GAStech_email_node.csv")
## Parsed with column specification:
## cols(
##   id = col_double(),
##   label = col_character(),
##   Department = col_character(),
##   Title = col_character()
## )
GAStech_edges <- read_csv("data/GAStech_email_edge-v2.csv")
## Parsed with column specification:
## cols(
##   source = col_double(),
##   target = col_double(),
##   SentDate = col_character(),
##   SentTime = col_time(format = ""),
##   Subject = col_character(),
##   MainSubject = col_character(),
##   sourceLabel = col_character(),
##   targetLabel = col_character()
## )
GAStech_edges$SentDate  = dmy(GAStech_edges$SentDate)
GAStech_edges$Weekday = wday(GAStech_edges$SentDate, label = TRUE, abbr = FALSE)
GAStech_edges_aggregated <- GAStech_edges %>%
  filter(MainSubject == "Work related") %>%
  group_by(source, target, Weekday) %>%
    summarise(Weight = n()) %>%
  filter(source!=target) %>%
  filter(Weight > 1) %>%
  ungroup()
GAStech_graph <- tbl_graph(nodes = GAStech_nodes, edges = GAStech_edges_aggregated, directed = TRUE)
GAStech_graph %>%
  activate(edges) %>%
  arrange(desc(Weight))
## # A tbl_graph: 54 nodes and 1456 edges
## #
## # A directed multigraph with 1 component
## #
## # Edge Data: 1,456 x 4 (active)
##    from    to Weekday Weight
##   <int> <int> <ord>    <int>
## 1    40    41 Tuesday     23
## 2    40    43 Tuesday     19
## 3    41    43 Tuesday     15
## 4    41    40 Tuesday     14
## 5    42    41 Tuesday     13
## 6    42    40 Tuesday     12
## # ... with 1,450 more rows
## #
## # Node Data: 54 x 4
##      id label           Department     Title           
##   <dbl> <chr>           <chr>          <chr>           
## 1     1 Mat.Bramar      Administration Assistant to CEO
## 2     2 Anda.Ribera     Administration Assistant to CFO
## 3     3 Rachel.Pantanal Administration Assistant to CIO
## # ... with 51 more rows

2.0 Task 1: Static Organisation Graph

With reference to the organisation network graph in Section 6.1 of Hands-on Exercise 10, you are required to complete the following tasks:

2.1 Improve the code chunk used to create the organisation network graph by using the latest functions provided in ggraph2.0.

Before Improvements:

g <- GAStech_graph %>%
  mutate(betweenness_centrality = centrality_betweenness()) %>%
  mutate(closeness_centrality = centrality_closeness()) %>%
  ggraph(layout = "nicely") + 
  geom_edge_link(aes()) +
  geom_node_point(aes(colour = closeness_centrality, size=betweenness_centrality))

g + theme_graph()

2.2 Impoved Code Chunk:

ggraph 2.0 utilizes the qgraph function. This function works as a Quickplot wrapper for networks.

We no longer need to create variables for closeness_centrality and betweenness_centrality as ggraph 2.0 can directly call these functions as inputs in the Aesthetic.

qgraph(
  GAStech_graph,
  node_colour = centrality_closeness(), 
  node_size = centrality_betweenness()
)+theme_graph()

2.3 Three Aspects of the visualization that can be imporoved are:

Problem: There is no indication of which node refers to which job title or Person

Solution: Use labels to indetify the nodes. I have used the job title as the identifying label.

Problem: No indication of which node refers to which department.

Solution: Use node outlines to specify which node belongs to which department.

Problem: The node edges are too dark which makes it difficult to see the nodes.

Solution: Use a lighter colour for the node edges.

2.4 Sketch of Alternate Design

Sketch_1

Sketch_1

2.5 Alternate Design:

alt_graph <- 
  ggraph(GAStech_graph, layout = "nicely") + 
  geom_edge_link(colour = "grey80") +
  #geom_node_point(aes( size=centrality_betweenness())) +
  geom_node_circle(aes(fill = centrality_closeness(),r=log(centrality_betweenness())/70, col = Department), size = 1) +
    
  geom_node_text(aes(label=GAStech_nodes$Title), size = 2, check_overlap = TRUE, repel = TRUE)
  

alt_graph + theme_graph()

3.0 Task 2: Interactive Organisation Graph

3.1 Data Preparation

GAStech_edges_aggregated <- GAStech_edges %>%
  left_join(GAStech_nodes, by = c("sourceLabel" = "label")) %>%
  rename(from = id) %>%
  left_join(GAStech_nodes, by = c("targetLabel" = "label")) %>%
  rename(to = id) %>%
  filter(MainSubject == "Work related") %>%
  group_by(from, to) %>%
    summarise(weight = n()) %>%
  filter(from!=to) %>%
  filter(weight > 1) %>%
  ungroup()

GAStech_nodes <- GAStech_nodes %>%
  rename(group = Department)

3.2 Original Design:

visNetwork(GAStech_nodes, GAStech_edges_aggregated) %>%
  visIgraphLayout(layout = "layout_with_fr") %>%
  visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

3.4 Adding interactivity

With reference to the organisation network graph in Section 7.4 of Hands-on Exercise 10, you are required to complete the following tasks:

Improve the design of the graph by incorporating the following interactivity:

  1. When a name is selected from the drop-down list, the corresponding node will not only be highlighted but also will be labelled. Furthermore, all the linked nodes of the selected node will also be labelled too.

  2. When a node of the interactive graph is selected, the node will not only be highlighted but also will be labelled. Furthermore, all the linked nodes of the selected node will be labelled as well.

3.5 Interactive Design

visNetwork(GAStech_nodes, GAStech_edges_aggregated) %>%
  visIgraphLayout(layout = "layout_with_fr") %>%
  visNodes(label=GAStech_nodes$id, shape="circle") %>%
  visOptions(highlightNearest = TRUE, nodesIdSelection = TRUE)

3.6 Three aspects to improve upon

Problem 1: We do not know which colour refers to which department

Solution: add a legend for the departments

Problem 2: Labels are not clearly visible

Solution: Add the labels to the centre of the graph and change node shape to box to clearly enclose the label.

Problem 3: Arrow directions are unknown

Solution: Add direction to the arrows

3.7 Sketch of Alternate Design

Sketch_2

Sketch_2

3.8 Alternate Design:

visNetwork(GAStech_nodes, GAStech_edges_aggregated) %>%
  visEdges(
    arrows = list(
      to = list(enabled = TRUE), 
      from = list(enabled = TRUE)
    )
  )%>%
  visIgraphLayout(layout = "layout_with_fr") %>%
  visNodes(label=GAStech_nodes$id ,shape="box") %>%
  #visOptions(selectedBy = "group")%>%
  visOptions(highlightNearest = list(enabled = TRUE, hover = T), nodesIdSelection = TRUE)%>%
    visInteraction(navigationButtons = TRUE)%>%
    visLegend(width = 0.3, position = "right", main = "Departments",zoom = FALSE)