### Load standardpackages
library(tidyverse) # Collection of all the good stuff like dplyr, ggplot2 ect.
library(magrittr) # For extra-piping operators (eg. %<>%)
library(tidygraph)
library(ggraph)

Danish elites data

Get the data

#remotes::install_github("antongrau/eliter") # Somehow doesnt work
#library(eliter)
dk_elites <- read_csv('https://github.com/SDS-AAU/SDS-master/raw/master/00_data/networks/elite_den17.csv') 
Rows: 56849 Columns: 16
── Column specification ───────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): NAME, AFFILIATION, ROLE, TAGS, SECTOR, TYPE, DESCRIPTION
dbl  (6): POSITION_ID, ID, CVR_PERSON, CVR_AFFILIATION, PERSON_ID, AFFILIATION_ID
lgl  (1): ARCHIVED
dttm (2): CREATED, LAST_CHECKED

ℹ 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.
data <- dk_elites

First Inspection & EDA

Initial cleaning

data %>% head()
data %>% glimpse()
Rows: 56,849
Columns: 16
$ NAME            <chr> "Aage Almtoft", "Aage B. Andersen", "Aage Christensen", "Aage Dam", "Aage…
$ AFFILIATION     <chr> "Middelfart Sparekasse", "Foreningen Ă˜stifterne - Repræsentantskab (Medle…
$ ROLE            <chr> "Member", "Member", "Chairman", "Chairman", "Member", "Member", "Member",…
$ TAGS            <chr> "Corporation, FINA, Banks, Finance", "Charity, Foundation, Insurance, Soc…
$ POSITION_ID     <dbl> 1, 4, 6, 8, 9, 15, 28, 30, 32, 34, 38, 41, 47, 49, 58, 63, 66, 70, 74, 76…
$ ID              <dbl> 95023, 67511, 100903, 69156, 72204, 73158, 100249, 3165, 72054, 72759, 86…
$ SECTOR          <chr> "Corporations", "NGO", "Foundations", "NGO", "NGO", "Parliament", "Corpor…
$ TYPE            <chr> NA, "Organisation", NA, "Organisation", "Stat", NA, NA, NA, NA, NA, NA, N…
$ DESCRIPTION     <chr> "Automatisk CVR import at 2016-03-12 18:01:28: BESTYRELSE i Middelfart Sp…
$ CREATED         <dttm> 2016-03-12 18:01:28, 2016-02-05 14:45:10, 2016-03-12 18:08:31, 2016-02-1…
$ ARCHIVED        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ LAST_CHECKED    <dttm> 2017-11-09 15:38:01, 2016-02-12 14:41:09, 2017-11-09 15:50:09, 2016-02-1…
$ CVR_PERSON      <dbl> 4003983591, NA, 4000054465, NA, NA, NA, 4003907021, NA, NA, NA, 400008157…
$ CVR_AFFILIATION <dbl> 24744817, NA, 29094411, NA, 43232010, NA, 25952200, NA, NA, 81191158, 666…
$ PERSON_ID       <dbl> 1, 3, 4, 5, 5, 9, 16, 18, 20, 21, 23, 25, 30, 31, 36, 38, 40, 43, 46, 47,…
$ AFFILIATION_ID  <dbl> 3687, 2528, 237, 469, 1041, 1781, 4878, 1038, 3535, 2733, 1532, 3509, 346…

Initial cleaning

colnames(data) <- colnames(data) %>% str_to_lower()

Selecting categories

data %>% count(role, sort = TRUE)
role_selected <- c('Member', 'Chairman', 'Vice chairman', 'Chief executive', 'Executive')
data %<>% filter(role %in% role_selected)
data %>% count(type, sort = TRUE)
# type_select <- c('Organisation', 'Virksomhed (CVR)') 
# data %<>% filter(type %in% type_select)
data %>% count(sector, sort = TRUE)
sector_select <- c('Corporations') 
data %<>% filter(sector %in% sector_select)

Create network

Edgelist

el_2m <- data %>%
  select(person_id, affiliation_id) 
el <- el_2m %>%
  left_join(el_2m %>% select(person_id, affiliation_id), by = "affiliation_id") 
el %<>% 
  select(-affiliation_id) %>%
  rename(from = person_id.x, 
         to = person_id.y) %>%
  filter(from != to)
el %<>%
  count(from, to, name = 'weight')  %>%
  mutate(weight = weight )
el %>% 
  arrange(desc(weight)) %>%
  head()
el %>% 
  ggplot(aes(x = weight)) +
  geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

nodes <- data %>%
  distinct(person_id, .keep_all = TRUE) %>%
  select(person_id, name) %>%
  rename(person_name = name,
         name = person_id) %>%
  mutate(name = name %>% as.character())

Create the graph

g <- el %>% as_tbl_graph(directed = FALSE)
g <- g %N>%
  left_join(nodes, by = 'name')

Degree centrality

g <- g %N>%
  mutate(cent_dgr = centrality_degree(weights = weight), 
         cent_eigen = centrality_eigen(weights = weight), # cent_between = centrality_betweenness(weights = weight) # takes long too compute
) 

Community structure

g <- g %N>%
  mutate(community = group_louvain(weights = weight) ) 
g %N>%
  as_tibble() %>%
  count(community)
# get rid of small communities
g <- g %N>%
  mutate(community = ifelse(community > 10, NA, community))
g <- g %N>%
  morph(to_split, community) %N>%
  mutate(cent_com = centrality_eigen(weight = weight),
         com_center = cent_com == max(cent_com),
         com_n = n()) %>%
  unmorph()
Subsetting by nodes
g %N>%
  as_tibble() %>%
  group_by(community) %>%
  arrange(desc(cent_com)) %>%
  slice(1:1) %>%
  ungroup()

Danske Bank

data %>% filter(affiliation %>% str_detect('Danske Bank'))
db_members <- data %>% 
  filter(affiliation_id == 932) %>%
  select(person_id) %>%
  distinct(person_id, .keep_all = TRUE) %>%
  rename(name = person_id) %>%
  mutate(name = name %>% as.character(),
         db_member = TRUE)

Plotting

General

set.seed(1337)

g  %N>% 
  filter(!is.na(community)) %>%
  mutate(community = community %>% as.factor()) %>%
  filter(percent_rank(centrality_eigen()) > 0.90 ) %>%
  filter(!node_is_isolated()) %>%
  # %E>% #filter(weight > 1) %>%
  ggraph(layout = 'fr') + 
  geom_edge_link(aes(alpha =  weight)) +
  geom_node_point(aes(size= cent_com, col = community)) +
  geom_node_text(aes(label = person_name, filter = com_center == TRUE), repel = TRUE) + 
  theme_graph() +
  theme(legend.position = 'bottom')

set.seed(1337)

g  %N>% 
  left_join(db_members, by = 'name') %>%
  mutate(db_member = ifelse(is.na(db_member), FALSE, db_member)) %>%
  filter(!is.na(community) | db_member == TRUE) %>%
  mutate(community = community %>% as.factor()) %>%
  filter(percent_rank(centrality_eigen()) > 0.80 | db_member == TRUE) %>%
  filter(!node_is_isolated()) %>%
  # %E>% #filter(weight > 1) %>%
  ggraph(layout = 'fr') + 
  geom_edge_link(aes(alpha =  weight)) +
  geom_node_point(aes(size= cent_com, col = db_member)) +
  geom_node_text(aes(label = person_name, filter = db_member == TRUE), repel = TRUE) + 
  theme_graph() +
  theme(legend.position = 'bottom')

Danske Bank seems here to be a bit isolated…

LS0tCnRpdGxlOiAnTmV0d29yayBBbmFseXNpcyBXb3Jrc2hvcDogQSBsb29rIGludG8gRGFuaXNoIEVsaXRlIE5ldHdvcmtzJwphdXRob3I6ICJEYW5pZWwgUy4gSGFpbiAoZHNoQGJ1c2luZXNzLmFhdS5kaykiCmRhdGU6ICJVcGRhdGVkIGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIgJWQsICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICB0aGVtZTogZmxhdGx5Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMjIyBHZW5lcmljIHByZWFtYmxlCnJtKGxpc3Q9bHMoKSkKU3lzLnNldGVudihMQU5HID0gImVuIikgIyBGb3IgZW5nbGlzaCBsYW5ndWFnZQpvcHRpb25zKHNjaXBlbiA9IDUpICMgVG8gZGVhY3RpdmF0ZSBhbm5veWluZyBzY2llbnRpZmljIG51bWJlciBub3RhdGlvbgoKIyMjIEtuaXRyIG9wdGlvbnMKbGlicmFyeShrbml0cikgIyBGb3IgZGlzcGxheSBvZiB0aGUgbWFya2Rvd24Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQ9RkFMU0UsIAogICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ249ImNlbnRlciIKICAgICAgICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQojIyMgTG9hZCBzdGFuZGFyZHBhY2thZ2VzCmxpYnJhcnkodGlkeXZlcnNlKSAjIENvbGxlY3Rpb24gb2YgYWxsIHRoZSBnb29kIHN0dWZmIGxpa2UgZHBseXIsIGdncGxvdDIgZWN0LgpsaWJyYXJ5KG1hZ3JpdHRyKSAjIEZvciBleHRyYS1waXBpbmcgb3BlcmF0b3JzIChlZy4gJTw+JSkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5Z3JhcGgpCmxpYnJhcnkoZ2dyYXBoKQpgYGAKCiMgRGFuaXNoIGVsaXRlcyBkYXRhCgotICAgPGh0dHBzOi8vZ2l0aHViLmNvbS9hbnRvbmdyYXUvZWxpdGVyPgotICAgPGh0dHBzOi8vbWFndGVsaXRlLmRrL2RhdGEvPgoKIyMgR2V0IHRoZSBkYXRhCgpgYGB7cn0KI3JlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCJhbnRvbmdyYXUvZWxpdGVyIikgIyBTb21laG93IGRvZXNudCB3b3JrCiNsaWJyYXJ5KGVsaXRlcikKYGBgCgpgYGB7cn0KZGtfZWxpdGVzIDwtIHJlYWRfY3N2KCdodHRwczovL2dpdGh1Yi5jb20vU0RTLUFBVS9TRFMtbWFzdGVyL3Jhdy9tYXN0ZXIvMDBfZGF0YS9uZXR3b3Jrcy9lbGl0ZV9kZW4xNy5jc3YnKSAKYGBgCgpgYGB7cn0KZGF0YSA8LSBka19lbGl0ZXMKYGBgCgojIEZpcnN0IEluc3BlY3Rpb24gJiBFREEKCiMjIEluaXRpYWwgY2xlYW5pbmcKCmBgYHtyfQpkYXRhICU+JSBoZWFkKCkKYGBgCgpgYGB7cn0KZGF0YSAlPiUgZ2xpbXBzZSgpCmBgYAoKIyMgSW5pdGlhbCBjbGVhbmluZwoKYGBge3J9CmNvbG5hbWVzKGRhdGEpIDwtIGNvbG5hbWVzKGRhdGEpICU+JSBzdHJfdG9fbG93ZXIoKQpgYGAKCiMjIFNlbGVjdGluZyBjYXRlZ29yaWVzCgpgYGB7cn0KZGF0YSAlPiUgY291bnQocm9sZSwgc29ydCA9IFRSVUUpCmBgYAoKYGBge3J9CnJvbGVfc2VsZWN0ZWQgPC0gYygnTWVtYmVyJywgJ0NoYWlybWFuJywgJ1ZpY2UgY2hhaXJtYW4nLCAnQ2hpZWYgZXhlY3V0aXZlJywgJ0V4ZWN1dGl2ZScpCmBgYAoKYGBge3J9CmRhdGEgJTw+JSBmaWx0ZXIocm9sZSAlaW4lIHJvbGVfc2VsZWN0ZWQpCmBgYAoKYGBge3J9CmRhdGEgJT4lIGNvdW50KHR5cGUsIHNvcnQgPSBUUlVFKQpgYGAKCmBgYHtyfQojIHR5cGVfc2VsZWN0IDwtIGMoJ09yZ2FuaXNhdGlvbicsICdWaXJrc29taGVkIChDVlIpJykgCiMgZGF0YSAlPD4lIGZpbHRlcih0eXBlICVpbiUgdHlwZV9zZWxlY3QpCmBgYAoKYGBge3J9CmRhdGEgJT4lIGNvdW50KHNlY3Rvciwgc29ydCA9IFRSVUUpCmBgYAoKCmBgYHtyfQpzZWN0b3Jfc2VsZWN0IDwtIGMoJ0NvcnBvcmF0aW9ucycpIApkYXRhICU8PiUgZmlsdGVyKHNlY3RvciAlaW4lIHNlY3Rvcl9zZWxlY3QpCmBgYAoKIyBDcmVhdGUgbmV0d29yawoKIyMgRWRnZWxpc3QKCmBgYHtyfQplbF8ybSA8LSBkYXRhICU+JQogIHNlbGVjdChwZXJzb25faWQsIGFmZmlsaWF0aW9uX2lkKSAKYGBgCgpgYGB7cn0KZWwgPC0gZWxfMm0gJT4lCiAgbGVmdF9qb2luKGVsXzJtICU+JSBzZWxlY3QocGVyc29uX2lkLCBhZmZpbGlhdGlvbl9pZCksIGJ5ID0gImFmZmlsaWF0aW9uX2lkIikgCmBgYAoKYGBge3J9CmVsICU8PiUgCiAgc2VsZWN0KC1hZmZpbGlhdGlvbl9pZCkgJT4lCiAgcmVuYW1lKGZyb20gPSBwZXJzb25faWQueCwgCiAgICAgICAgIHRvID0gcGVyc29uX2lkLnkpICU+JQogIGZpbHRlcihmcm9tICE9IHRvKQpgYGAKCmBgYHtyfQplbCAlPD4lCiAgY291bnQoZnJvbSwgdG8sIG5hbWUgPSAnd2VpZ2h0JykgICU+JQogIG11dGF0ZSh3ZWlnaHQgPSB3ZWlnaHQgKQpgYGAKCmBgYHtyfQplbCAlPiUgCiAgYXJyYW5nZShkZXNjKHdlaWdodCkpICU+JQogIGhlYWQoKQpgYGAKCmBgYHtyfQplbCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0KSkgKwogIGdlb21faGlzdG9ncmFtKCkKYGBgCgpgYGB7cn0Kbm9kZXMgPC0gZGF0YSAlPiUKICBkaXN0aW5jdChwZXJzb25faWQsIC5rZWVwX2FsbCA9IFRSVUUpICU+JQogIHNlbGVjdChwZXJzb25faWQsIG5hbWUpICU+JQogIHJlbmFtZShwZXJzb25fbmFtZSA9IG5hbWUsCiAgICAgICAgIG5hbWUgPSBwZXJzb25faWQpICU+JQogIG11dGF0ZShuYW1lID0gbmFtZSAlPiUgYXMuY2hhcmFjdGVyKCkpCmBgYAoKCiMjIENyZWF0ZSB0aGUgZ3JhcGgKCmBgYHtyfQpnIDwtIGVsICU+JSBhc190YmxfZ3JhcGgoZGlyZWN0ZWQgPSBGQUxTRSkKYGBgCgpgYGB7cn0KZyA8LSBnICVOPiUKICBsZWZ0X2pvaW4obm9kZXMsIGJ5ID0gJ25hbWUnKQpgYGAKCiMjIERlZ3JlZSBjZW50cmFsaXR5CgpgYGB7cn0KZyA8LSBnICVOPiUKICBtdXRhdGUoY2VudF9kZ3IgPSBjZW50cmFsaXR5X2RlZ3JlZSh3ZWlnaHRzID0gd2VpZ2h0KSwgCiAgICAgICAgIGNlbnRfZWlnZW4gPSBjZW50cmFsaXR5X2VpZ2VuKHdlaWdodHMgPSB3ZWlnaHQpLCAjIGNlbnRfYmV0d2VlbiA9IGNlbnRyYWxpdHlfYmV0d2Vlbm5lc3Mod2VpZ2h0cyA9IHdlaWdodCkgIyB0YWtlcyBsb25nIHRvbyBjb21wdXRlCikgCmBgYAoKCiMjIENvbW11bml0eSBzdHJ1Y3R1cmUKCmBgYHtyfQpnIDwtIGcgJU4+JQogIG11dGF0ZShjb21tdW5pdHkgPSBncm91cF9sb3V2YWluKHdlaWdodHMgPSB3ZWlnaHQpICkgCmBgYAoKYGBge3J9CmcgJU4+JQogIGFzX3RpYmJsZSgpICU+JQogIGNvdW50KGNvbW11bml0eSkKYGBgCgpgYGB7cn0KIyBnZXQgcmlkIG9mIHNtYWxsIGNvbW11bml0aWVzCmcgPC0gZyAlTj4lCiAgbXV0YXRlKGNvbW11bml0eSA9IGlmZWxzZShjb21tdW5pdHkgPiAxMCwgTkEsIGNvbW11bml0eSkpCmBgYAoKYGBge3J9CmcgPC0gZyAlTj4lCiAgbW9ycGgodG9fc3BsaXQsIGNvbW11bml0eSkgJU4+JQogIG11dGF0ZShjZW50X2NvbSA9IGNlbnRyYWxpdHlfZWlnZW4od2VpZ2h0ID0gd2VpZ2h0KSwKICAgICAgICAgY29tX2NlbnRlciA9IGNlbnRfY29tID09IG1heChjZW50X2NvbSksCiAgICAgICAgIGNvbV9uID0gbigpKSAlPiUKICB1bm1vcnBoKCkKYGBgCgpgYGB7cn0KZyAlTj4lCiAgYXNfdGliYmxlKCkgJT4lCiAgZ3JvdXBfYnkoY29tbXVuaXR5KSAlPiUKICBhcnJhbmdlKGRlc2MoY2VudF9jb20pKSAlPiUKICBzbGljZSgxOjEpICU+JQogIHVuZ3JvdXAoKQpgYGAKCiMjIERhbnNrZSBCYW5rCgpgYGB7cn0KZGF0YSAlPiUgZmlsdGVyKGFmZmlsaWF0aW9uICU+JSBzdHJfZGV0ZWN0KCdEYW5za2UgQmFuaycpKQpgYGAKCmBgYHtyfQpkYl9tZW1iZXJzIDwtIGRhdGEgJT4lIAogIGZpbHRlcihhZmZpbGlhdGlvbl9pZCA9PSA5MzIpICU+JQogIHNlbGVjdChwZXJzb25faWQpICU+JQogIGRpc3RpbmN0KHBlcnNvbl9pZCwgLmtlZXBfYWxsID0gVFJVRSkgJT4lCiAgcmVuYW1lKG5hbWUgPSBwZXJzb25faWQpICU+JQogIG11dGF0ZShuYW1lID0gbmFtZSAlPiUgYXMuY2hhcmFjdGVyKCksCiAgICAgICAgIGRiX21lbWJlciA9IFRSVUUpCmBgYAoKIyMgUGxvdHRpbmcKCiMjIyBHZW5lcmFsCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTE1fQpzZXQuc2VlZCgxMzM3KQoKZyAgJU4+JSAKICBmaWx0ZXIoIWlzLm5hKGNvbW11bml0eSkpICU+JQogIG11dGF0ZShjb21tdW5pdHkgPSBjb21tdW5pdHkgJT4lIGFzLmZhY3RvcigpKSAlPiUKICBmaWx0ZXIocGVyY2VudF9yYW5rKGNlbnRyYWxpdHlfZWlnZW4oKSkgPiAwLjkwICkgJT4lCiAgZmlsdGVyKCFub2RlX2lzX2lzb2xhdGVkKCkpICU+JQogICMgJUU+JSAjZmlsdGVyKHdlaWdodCA+IDEpICU+JQogIGdncmFwaChsYXlvdXQgPSAnZnInKSArIAogIGdlb21fZWRnZV9saW5rKGFlcyhhbHBoYSA9ICB3ZWlnaHQpKSArCiAgZ2VvbV9ub2RlX3BvaW50KGFlcyhzaXplPSBjZW50X2NvbSwgY29sID0gY29tbXVuaXR5KSkgKwogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IHBlcnNvbl9uYW1lLCBmaWx0ZXIgPSBjb21fY2VudGVyID09IFRSVUUpLCByZXBlbCA9IFRSVUUpICsgCiAgdGhlbWVfZ3JhcGgoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xNX0Kc2V0LnNlZWQoMTMzNykKCmcgICVOPiUgCiAgbGVmdF9qb2luKGRiX21lbWJlcnMsIGJ5ID0gJ25hbWUnKSAlPiUKICBtdXRhdGUoZGJfbWVtYmVyID0gaWZlbHNlKGlzLm5hKGRiX21lbWJlciksIEZBTFNFLCBkYl9tZW1iZXIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGNvbW11bml0eSkgfCBkYl9tZW1iZXIgPT0gVFJVRSkgJT4lCiAgbXV0YXRlKGNvbW11bml0eSA9IGNvbW11bml0eSAlPiUgYXMuZmFjdG9yKCkpICU+JQogIGZpbHRlcihwZXJjZW50X3JhbmsoY2VudHJhbGl0eV9laWdlbigpKSA+IDAuODAgfCBkYl9tZW1iZXIgPT0gVFJVRSkgJT4lCiAgZmlsdGVyKCFub2RlX2lzX2lzb2xhdGVkKCkpICU+JQogICMgJUU+JSAjZmlsdGVyKHdlaWdodCA+IDEpICU+JQogIGdncmFwaChsYXlvdXQgPSAnZnInKSArIAogIGdlb21fZWRnZV9saW5rKGFlcyhhbHBoYSA9ICB3ZWlnaHQpKSArCiAgZ2VvbV9ub2RlX3BvaW50KGFlcyhzaXplPSBjZW50X2NvbSwgY29sID0gZGJfbWVtYmVyKSkgKwogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IHBlcnNvbl9uYW1lLCBmaWx0ZXIgPSBkYl9tZW1iZXIgPT0gVFJVRSksIHJlcGVsID0gVFJVRSkgKyAKICB0aGVtZV9ncmFwaCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykKYGBgCkRhbnNrZSBCYW5rIHNlZW1zIGhlcmUgdG8gYmUgYSBiaXQgaXNvbGF0ZWQuLi4K