### 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
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 Dam", "Aage Frandsen", "Aage Juhl Jørgensen…
$ AFFILIATION     <chr> "Middelfart Sparekasse", "Foreningen Østifterne - Repræsentantskab (Medlemmer af delegeretforsamling)", "ÅRHUS SØMAND…
$ ROLE            <chr> "Member", "Member", "Chairman", "Chairman", "Member", "Member", "Member", "Member", "Member", "Member", "Member", "Me…
$ TAGS            <chr> "Corporation, FINA, Banks, Finance", "Charity, Foundation, Insurance, Socialomraadet", "Foundation, Marine, Tourism",…
$ POSITION_ID     <dbl> 1, 4, 6, 8, 9, 15, 28, 30, 32, 34, 38, 41, 47, 49, 58, 63, 66, 70, 74, 76, 78, 80, 96, 104, 113, 115, 131, 133, 135, …
$ ID              <dbl> 95023, 67511, 100903, 69156, 72204, 73158, 100249, 3165, 72054, 72759, 86531, 71070, 70858, 137228, 100956, 89846, 34…
$ SECTOR          <chr> "Corporations", "NGO", "Foundations", "NGO", "NGO", "Parliament", "Corporations", "NGO", "NGO", "NGO", "Foundations",…
$ TYPE            <chr> NA, "Organisation", NA, "Organisation", "Stat", NA, NA, NA, NA, NA, NA, NA, NA, "Netværk (VL-gruppe)", NA, NA, NA, NA…
$ DESCRIPTION     <chr> "Automatisk CVR import at 2016-03-12 18:01:28: BESTYRELSE i Middelfart Sparekasse (2009-03-31 - ).", "Direktør", "Aut…
$ CREATED         <dttm> 2016-03-12 18:01:28, 2016-02-05 14:45:10, 2016-03-12 18:08:31, 2016-02-10 15:18:47, 2016-02-16 10:49:01, 2016-02-17 …
$ ARCHIVED        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 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-10 14:19:20, 2016-02-16 11:55:34, 2016-02-17 …
$ CVR_PERSON      <dbl> 4003983591, NA, 4000054465, NA, NA, NA, 4003907021, NA, NA, NA, 4000081578, NA, NA, 4003899511, 4004108676, 400416014…
$ CVR_AFFILIATION <dbl> 24744817, NA, 29094411, NA, 43232010, NA, 25952200, NA, NA, 81191158, 66693511, 37282146, 84414913, NA, 25059115, 107…
$ PERSON_ID       <dbl> 1, 3, 4, 5, 5, 9, 16, 18, 20, 21, 23, 25, 30, 31, 36, 38, 40, 43, 46, 47, 47, 49, 60, 63, 68, 69, 81, 82, 82, 82, 82,…
$ AFFILIATION_ID  <dbl> 3687, 2528, 237, 469, 1041, 1781, 4878, 1038, 3535, 2733, 1532, 3509, 3462, 8426, 37, 2372, 1065, 2760, 2202, 5536, 1…

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)

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') 
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)) %>%
  arrange(desc(cent_between))

Community structure

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

Plotting

set.seed(1337)
g  %N>% 
  filter(!is.na(community)) %>%
  mutate(community = community %>% as.factor()) %>%
  filter(percent_rank(cent_eigen) > 0.95 ) %>%
  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')

LS0tCnRpdGxlOiAnTmV0d29yayBBbmFseXNpcyBXb3Jrc2hvcDogQSBsb29rIGludG8gRGFuaXNoIEVsaXRlIE5ldHdvcmtzJwphdXRob3I6ICJEYW5pZWwgUy4gSGFpbiAoZHNoQGJ1c2luZXNzLmFhdS5kaykiCmRhdGU6ICJVcGRhdGVkIGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIgJWQsICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICB0aGVtZTogZmxhdGx5Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMjIyBHZW5lcmljIHByZWFtYmxlCnJtKGxpc3Q9bHMoKSkKU3lzLnNldGVudihMQU5HID0gImVuIikgIyBGb3IgZW5nbGlzaCBsYW5ndWFnZQpvcHRpb25zKHNjaXBlbiA9IDUpICMgVG8gZGVhY3RpdmF0ZSBhbm5veWluZyBzY2llbnRpZmljIG51bWJlciBub3RhdGlvbgoKIyMjIEtuaXRyIG9wdGlvbnMKbGlicmFyeShrbml0cikgIyBGb3IgZGlzcGxheSBvZiB0aGUgbWFya2Rvd24Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHdhcm5pbmc9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQ9RkFMU0UsIAogICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ249ImNlbnRlciIKICAgICAgICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQojIyMgTG9hZCBzdGFuZGFyZHBhY2thZ2VzCmxpYnJhcnkodGlkeXZlcnNlKSAjIENvbGxlY3Rpb24gb2YgYWxsIHRoZSBnb29kIHN0dWZmIGxpa2UgZHBseXIsIGdncGxvdDIgZWN0LgpsaWJyYXJ5KG1hZ3JpdHRyKSAjIEZvciBleHRyYS1waXBpbmcgb3BlcmF0b3JzIChlZy4gJTw+JSkKYGBgCgpgYGB7cn0KbGlicmFyeSh0aWR5Z3JhcGgpCmxpYnJhcnkoZ2dyYXBoKQpgYGAKCiMgRGFuaXNoIGVsaXRlcyBkYXRhCgoqIGh0dHBzOi8vZ2l0aHViLmNvbS9hbnRvbmdyYXUvZWxpdGVyCiogaHR0cHM6Ly9tYWd0ZWxpdGUuZGsvZGF0YS8KCiMjIEdldCB0aGUgZGF0YQoKYGBge3J9CiMgcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoImFudG9uZ3JhdS9lbGl0ZXIiKSAjIFNvbWVob3cgZG9lc250IHdvcmsKYGBgCgpgYGB7cn0KZGtfZWxpdGVzIDwtIHJlYWRfY3N2KCdodHRwczovL2dpdGh1Yi5jb20vU0RTLUFBVS9TRFMtbWFzdGVyL3Jhdy9tYXN0ZXIvMDBfZGF0YS9uZXR3b3Jrcy9lbGl0ZV9kZW4xNy5jc3YnKSAKYGBgCmBgYHtyfQpkYXRhIDwtIGRrX2VsaXRlcwpgYGAKCgojIEZpcnN0IEluc3BlY3Rpb24gJiBFREEKCiMjIEluaXRpYWwgY2xlYW5pbmcKCmBgYHtyfQpkYXRhICU+JSBoZWFkKCkKYGBgCgpgYGB7cn0KZGF0YSAlPiUgZ2xpbXBzZSgpCmBgYAoKIyMgSW5pdGlhbCBjbGVhbmluZwoKYGBge3J9CmNvbG5hbWVzKGRhdGEpIDwtIGNvbG5hbWVzKGRhdGEpICU+JSBzdHJfdG9fbG93ZXIoKQpgYGAKCgojIyBTZWxlY3RpbmcgY2F0ZWdvcmllcwoKYGBge3J9CmRhdGEgJT4lIGNvdW50KHJvbGUsIHNvcnQgPSBUUlVFKQpgYGAKCmBgYHtyfQpyb2xlX3NlbGVjdGVkIDwtIGMoJ01lbWJlcicsICdDaGFpcm1hbicsICdWaWNlIGNoYWlybWFuJywgJ0NoaWVmIGV4ZWN1dGl2ZScsICdFeGVjdXRpdmUnKQpgYGAKCmBgYHtyfQpkYXRhICU8PiUgZmlsdGVyKHJvbGUgJWluJSByb2xlX3NlbGVjdGVkKQpgYGAKCmBgYHtyfQpkYXRhICU+JSBjb3VudCh0eXBlLCBzb3J0ID0gVFJVRSkKYGBgCgpgYGB7cn0KdHlwZV9zZWxlY3QgPC0gYygnT3JnYW5pc2F0aW9uJywgJ1Zpcmtzb21oZWQgKENWUiknKSAKYGBgCgoKYGBge3J9CmRhdGEgJTw+JSBmaWx0ZXIodHlwZSAlaW4lIHR5cGVfc2VsZWN0KQpgYGAKCiMgQ3JlYXRlIG5ldHdvcmsKCiMjIEVkZ2VsaXN0CgpgYGB7cn0KZWxfMm0gPC0gZGF0YSAlPiUKICBzZWxlY3QocGVyc29uX2lkLCBhZmZpbGlhdGlvbl9pZCkgCmBgYAoKYGBge3J9CmVsIDwtIGVsXzJtICU+JQogIGxlZnRfam9pbihlbF8ybSAlPiUgc2VsZWN0KHBlcnNvbl9pZCwgYWZmaWxpYXRpb25faWQpLCBieSA9ICJhZmZpbGlhdGlvbl9pZCIpIApgYGAKCgoKYGBge3J9CmVsICU8PiUgCiAgc2VsZWN0KC1hZmZpbGlhdGlvbl9pZCkgJT4lCiAgcmVuYW1lKGZyb20gPSBwZXJzb25faWQueCwgCiAgICAgICAgIHRvID0gcGVyc29uX2lkLnkpICU+JQogIGZpbHRlcihmcm9tICE9IHRvKQpgYGAKCmBgYHtyfQplbCAlPD4lCiAgY291bnQoZnJvbSwgdG8sIG5hbWUgPSAnd2VpZ2h0JykgCmBgYAoKYGBge3J9CmVsICU+JSAKICBhcnJhbmdlKGRlc2Mod2VpZ2h0KSkgJT4lCiAgaGVhZCgpCmBgYApgCmBgYHtyfQplbCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0KSkgKwogIGdlb21faGlzdG9ncmFtKCkKYGBgCgoKYGBge3J9Cm5vZGVzIDwtIGRhdGEgJT4lCiAgZGlzdGluY3QocGVyc29uX2lkLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUKICBzZWxlY3QocGVyc29uX2lkLCBuYW1lKSAlPiUKICByZW5hbWUocGVyc29uX25hbWUgPSBuYW1lLAogICAgICAgICBuYW1lID0gcGVyc29uX2lkKSAlPiUKICBtdXRhdGUobmFtZSA9IG5hbWUgJT4lIGFzLmNoYXJhY3RlcigpKQpgYGAKCiMjIENyZWF0ZSB0aGUgZ3JhcGgKCmBgYHtyfQpnIDwtIGVsICU+JSBhc190YmxfZ3JhcGgoZGlyZWN0ZWQgPSBGQUxTRSkKYGBgCgpgYGB7cn0KZyA8LSBnICVOPiUKICBsZWZ0X2pvaW4obm9kZXMsIGJ5ID0gJ25hbWUnKQpgYGAKCiMjIERlZ3JlZSBjZW50cmFsaXR5CgpgYGB7cn0KZyA8LSBnICVOPiUKICBtdXRhdGUoY2VudF9kZ3IgPSBjZW50cmFsaXR5X2RlZ3JlZSh3ZWlnaHRzID0gd2VpZ2h0KSwKICAgICAgICAgY2VudF9laWdlbiA9IGNlbnRyYWxpdHlfZWlnZW4od2VpZ2h0cyA9IHdlaWdodCksCiAgICAgICAgIGNlbnRfYmV0d2VlbiA9IGNlbnRyYWxpdHlfYmV0d2Vlbm5lc3Mod2VpZ2h0cyA9IHdlaWdodCkpICU+JQogIGFycmFuZ2UoZGVzYyhjZW50X2JldHdlZW4pKQpgYGAKCiMjIENvbW11bml0eSBzdHJ1Y3R1cmUKCmBgYHtyfQpnIDwtIGcgJU4+JQogIG11dGF0ZShjb21tdW5pdHkgPSBncm91cF9sb3V2YWluKHdlaWdodHMgPSB3ZWlnaHQpICkKYGBgCgpgYGB7cn0KZyAlTj4lCiAgYXNfdGliYmxlKCkgJT4lCiAgY291bnQoY29tbXVuaXR5KQpgYGAKCmBgYHtyfQpnIDwtIGcgJU4+JQogIG11dGF0ZShjb21tdW5pdHkgPSBpZmVsc2UoY29tbXVuaXR5ID4gMTAsIE5BLCBjb21tdW5pdHkpKQpgYGAKCmBgYHtyfQpnICVOPiUKICBhc190aWJibGUoKSAlPiUKICBjb3VudChjb21tdW5pdHkpCmBgYAoKYGBge3J9CmcgPC0gZyAlTj4lCiAgbW9ycGgodG9fc3BsaXQsIGNvbW11bml0eSkgJU4+JQogIG11dGF0ZShjZW50X2NvbSA9IGNlbnRyYWxpdHlfZWlnZW4od2VpZ2h0ID0gd2VpZ2h0KSwKICAgICAgICAgY29tX2NlbnRlciA9IGNlbnRfY29tID09IG1heChjZW50X2NvbSkpICU+JQogIHVubW9ycGgoKQpgYGAKYGBge3J9CmcgJU4+JQogIGFzX3RpYmJsZSgpICU+JQogIGdyb3VwX2J5KGNvbW11bml0eSkgJT4lCiAgYXJyYW5nZShkZXNjKGNlbnRfY29tKSkgJT4lCiAgc2xpY2UoMToxKSAlPiUKICB1bmdyb3VwKCkKYGBgCgojIyBQbG90dGluZwoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xNX0Kc2V0LnNlZWQoMTMzNykKZyAgJU4+JSAKICBmaWx0ZXIoIWlzLm5hKGNvbW11bml0eSkpICU+JQogIG11dGF0ZShjb21tdW5pdHkgPSBjb21tdW5pdHkgJT4lIGFzLmZhY3RvcigpKSAlPiUKICBmaWx0ZXIocGVyY2VudF9yYW5rKGNlbnRfZWlnZW4pID4gMC45NSApICU+JQogIGZpbHRlcighbm9kZV9pc19pc29sYXRlZCgpKSAlPiUKICAjICVFPiUgI2ZpbHRlcih3ZWlnaHQgPiAxKSAlPiUKICBnZ3JhcGgobGF5b3V0ID0gJ2ZyJykgKyAKICBnZW9tX2VkZ2VfbGluayhhZXMoYWxwaGEgPSAgd2VpZ2h0KSkgKwogIGdlb21fbm9kZV9wb2ludChhZXMoc2l6ZT0gY2VudF9jb20sIGNvbCA9IGNvbW11bml0eSkpICsKICBnZW9tX25vZGVfdGV4dChhZXMobGFiZWwgPSBwZXJzb25fbmFtZSwgZmlsdGVyID0gY29tX2NlbnRlciA9PSBUUlVFKSwgcmVwZWwgPSBUUlVFKSArIAogIHRoZW1lX2dyYXBoKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdib3R0b20nKQpgYGAKCgo=