1 Fourth Deliverable

Replicate the interactive network visualization but relying on your publication data. 1. Decide whether you want to plot the co-author relationship starting from the one-mode network or whether you want to link authors to papers and then transform this to a one-mode network. Recall that the latter retains solo authors, in case you have those in your data set.

I decided to start from the two mode network because I wanted to retain the solo authors in my data set.

  1. Whatever you decide, explain why you selected to map the co-authors or start with the two-mode form and the get the co-authors vial network transformation.

I started with two-mode form and then get the co-author via transformation because I want to retain solo authors in the network.

  1. Make sure you add a meaningful attribute to their connecting line, In our case we number of courses in common. You can add number of co-publications, for example. Finally, tell us WHY should we even care about doing all of this (or do we)?

We wanted to visualize the data through this progress because we want this data-storytelling process to be more interactive, more informative, and it will also help validate our methodological narrative in return.

########################Complex Systems Networks##########################
library(igraph)
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
library(splitstackshape)

getwd()
## [1] "/Users/aihe/Desktop/UPenn/[Summer 23] SSNA"
setwd("/Users/aihe/Desktop")
source <- read.csv("AI_SLL.csv")

# clean the data, keep only authors and articles
source <- source[source$Author.s..ID!="[No author id available]",]

### create a author-author matrix through transformation of a two-mode edgelist#
authors <- as.data.frame(source[,2])

colnames(authors) <- "AU"

source_split <- cSplit(authors, splitCols = "AU", sep = ";", direction = "wide", drop = TRUE)
## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE
#No needed but just in case
source_split <- data.frame(lapply(source_split, trimws), stringsAsFactors = FALSE)
mat_source_split <- as.matrix(source_split)

combined <- cbind(source$EID, mat_source_split)

mat_combined_eid_source_split <- as.matrix(combined)

edgelist_two_mode <- cbind(mat_combined_eid_source_split[, 1], c(mat_combined_eid_source_split[, -1]))
edgelist_two_mode <- edgelist_two_mode[!is.na(edgelist_two_mode[,2]), ]
df_edgelist_twomode <- as.data.frame(edgelist_two_mode)
#this is edgelist between EID & author ID (w/ replication)

head(edgelist_two_mode)
##      [,1]                 [,2]         
## [1,] "2-s2.0-85143794140" "57223640712"
## [2,] "2-s2.0-85160812282" "57753915200"
## [3,] "2-s2.0-85160269286" "58288848400"
## [4,] "2-s2.0-85159570136" "58258344100"
## [5,] "2-s2.0-85158902849" "58061860400"
## [6,] "2-s2.0-85147960691" "57301216200"
dim(edgelist_two_mode)
## [1] 737   2
g2 <- graph.edgelist(edgelist_two_mode[, 2:1], directed = TRUE)
g2
## IGRAPH 0e29c60 DN-- 906 737 -- 
## + attr: name (v/c)
## + edges from 0e29c60 (vertex names):
##  [1] 57223640712->2-s2.0-85143794140 57753915200->2-s2.0-85160812282
##  [3] 58288848400->2-s2.0-85160269286 58258344100->2-s2.0-85159570136
##  [5] 58061860400->2-s2.0-85158902849 57301216200->2-s2.0-85147960691
##  [7] 50262958000->2-s2.0-85148333106 57221813377->2-s2.0-85142524779
##  [9] 57769896800->2-s2.0-85132609552 41561548400->2-s2.0-85159058001
## [11] 57222072140->2-s2.0-85156121354 58205160300->2-s2.0-85154056174
## [13] 57191156064->2-s2.0-85152072289 58158727000->2-s2.0-85150968581
## [15] 57209902552->2-s2.0-85150939650 57211158344->2-s2.0-85150790502
## + ... omitted several edges
g2 <- graph.edgelist(edgelist_two_mode[, 2:1], directed = FALSE) 
plot(g2)

# which one is it?

V(g2)$type <- V(g2)$name %in% edgelist_two_mode[ , 1]
table(V(g2)$type)
## 
## FALSE  TRUE 
##   727   179
#creating ID bank
getwd()
## [1] "/Users/aihe/Desktop"
source <- read.csv("/Users/aihe/Desktop/AI_SLL.csv")
source <- source[source$Author.s..ID!="[No author id available]",]
source$au <- gsub(" Jr.,", "", 
                  gsub(" II.,", "", 
                       gsub(" Jr.", "",
                            gsub(" M.S.", "",
                                 gsub(" M.S.,", "",
                                      gsub(" II.", "", source[,1]))))))
source$au <- gsub("\\.,", ";", source$au)
source$au <- tolower(source$au)
df_all_authors <- as.data.frame(source[ , ncol(source)])
colnames(df_all_authors) <- "AU"

authornames_split <- cSplit(df_all_authors, splitCols = "AU", sep = ";", direction = "wide", drop = TRUE)
## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE
dim(authornames_split)
## [1] 179  41
df_authors_id <- as.data.frame(source[ , 2])
colnames(df_authors_id) <- "AU"
author_id_split <- cSplit(df_authors_id, splitCols = "AU", sep = ";", direction = "wide", drop = TRUE) 
## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE

## Warning in type.convert.default(X[[i]], ...): 'as.is' should be specified by
## the caller; using TRUE
dim(author_id_split)
## [1] 179  41
df_authorid_authorname_unlisted <- data.frame(id = unlist(author_id_split), names = unlist(authornames_split))
df_authorid_authorname_unlisted <- df_authorid_authorname_unlisted[!is.na(df_authorid_authorname_unlisted$id),]
dim(df_authorid_authorname_unlisted)
## [1] 737   2
df_authorid_authorname_unlisted <- df_authorid_authorname_unlisted[!duplicated(df_authorid_authorname_unlisted$id),]
dim(df_authorid_authorname_unlisted)
## [1] 727   2
df_edgelist_twomode$names <- df_authorid_authorname_unlisted$names[match(df_edgelist_twomode$V2, df_authorid_authorname_unlisted$id)]
#####Add pub_count as an attribute at the edge level
pub_count <- as.data.frame(table(unlist(author_id_split)))
#df_authorid_authorname_unlisted$pub_count <- pub_count$Freq[match(df_authorid_authorname_unlisted$id, pub_count$Var1)]

a <- df_edgelist_twomode
g<-graph.data.frame(a[,c("V2","V1")])
g
## IGRAPH a9e738e DN-- 906 737 -- 
## + attr: name (v/c)
## + edges from a9e738e (vertex names):
##  [1] 57223640712->2-s2.0-85143794140 57753915200->2-s2.0-85160812282
##  [3] 58288848400->2-s2.0-85160269286 58258344100->2-s2.0-85159570136
##  [5] 58061860400->2-s2.0-85158902849 57301216200->2-s2.0-85147960691
##  [7] 50262958000->2-s2.0-85148333106 57221813377->2-s2.0-85142524779
##  [9] 57769896800->2-s2.0-85132609552 41561548400->2-s2.0-85159058001
## [11] 57222072140->2-s2.0-85156121354 58205160300->2-s2.0-85154056174
## [13] 57191156064->2-s2.0-85152072289 58158727000->2-s2.0-85150968581
## [15] 57209902552->2-s2.0-85150939650 57211158344->2-s2.0-85150790502
## + ... omitted several edges
#Need the two-mode edgelist from Deliverable 3 (EID+names+IDs) --> g2

#The following code adds the two-mode structure to the graph "g"
V(g)$type <- V(g)$name %in% a[,c("V2")] 
table(V(g)$type)[2]
## TRUE 
##  727
i<-table(V(g)$type)[2]

#Gets centrality measures
cent<-data.frame(bet=betweenness(g, normalized=T, directed = FALSE)/max(betweenness(g, normalized=T, directed = FALSE)),eig=evcent(g)$vector, degree=degree(g, mode="total")) 
cent$name<-rownames(cent) #Ids in this case
head(cent);tail(cent)
##                     bet eig degree        name
## 57223640712 0.000000000   0      1 57223640712
## 57753915200 0.000000000   0      1 57753915200
## 58288848400 0.000000000   0      1 58288848400
## 58258344100 0.000000000   0      1 58258344100
## 58061860400 0.004878049   0      2 58061860400
## 57301216200 0.000000000   0      1 57301216200
##                            bet eig degree               name
## 2-s2.0-85063775408 0.003658537   0      3 2-s2.0-85063775408
## 2-s2.0-85047475402 0.001219512   0      2 2-s2.0-85047475402
## 2-s2.0-85050231849 0.000000000   0      1 2-s2.0-85050231849
## 2-s2.0-85021632458 0.000000000   0      1 2-s2.0-85021632458
## 2-s2.0-85058058613 0.001219512   0      2 2-s2.0-85058058613
## 2-s2.0-85049375044 0.000000000   0      1 2-s2.0-85049375044
###
cent$bet[1:i]<-cent$bet[1:i]/max(cent$bet[1:i])
cent$eig[1:i]<-cent$eig[1:i]/max(cent$eig[1:i])
summary(cent[1:i,])
##       bet                eig             degree          name          
##  Min.   :0.000000   Min.   :0.0000   Min.   :1.000   Length:727        
##  1st Qu.:0.000000   1st Qu.:0.0000   1st Qu.:1.000   Class :character  
##  Median :0.000000   Median :0.0000   Median :1.000   Mode  :character  
##  Mean   :0.001501   Mean   :0.0564   Mean   :1.014                     
##  3rd Qu.:0.000000   3rd Qu.:0.0000   3rd Qu.:1.000                     
##  Max.   :1.000000   Max.   :1.0000   Max.   :2.000
cent$bet[(i+1):nrow(cent)]<-cent$bet[(i+1):nrow(cent)]/max(cent$bet[(i+1):nrow(cent)])
cent$eig[(i+1):nrow(cent)]<-cent$eig[(i+1):nrow(cent)]/max(cent$eig[(i+1):nrow(cent)])
summary(cent[(i+1):nrow(cent),])
##       bet                eig               degree           name          
##  Min.   :0.000000   Min.   :0.000000   Min.   : 1.000   Length:179        
##  1st Qu.:0.001220   1st Qu.:0.000000   1st Qu.: 2.000   Class :character  
##  Median :0.003658   Median :0.000000   Median : 3.000   Mode  :character  
##  Mean   :0.019110   Mean   :0.005587   Mean   : 4.117                     
##  3rd Qu.:0.012195   3rd Qu.:0.000000   3rd Qu.: 5.000                     
##  Max.   :1.000000   Max.   :1.000000   Max.   :41.000
#Gets time invariant actor attributes
#actors<- source[!duplicated(source$Author.s..ID), c("Author.s..ID", "Year")]

#Transformation to one-mode
mat_g2_incidence <- get.incidence(g2)

mat_g2_incidence_to_1 <- mat_g2_incidence%*%t(mat_g2_incidence)

diag(mat_g2_incidence_to_1)<-0

g <- graph.adjacency(mat_g2_incidence_to_1, mode = "undirected")
g
## IGRAPH 3017fae UN-- 727 2540 -- 
## + attr: name (v/c)
## + edges from 3017fae (vertex names):
##  [1] 57223640712--14627618600 57223640712--56412981200 57753915200--57209094353
##  [4] 58288848400--58289105500 58288848400--58289499100 58288848400--57570827800
##  [7] 58288848400--57200371657 58288848400--6508378209  58288848400--58289499200
## [10] 58288848400--58289499300 58288848400--58288979300 58288848400--57201813646
## [13] 58061860400--58241995800 58061860400--57204101861 57301216200--57200151370
## [16] 50262958000--7005495251  50262958000--57220804469 57221813377--57063266900
## [19] 57221813377--57063266900 57221813377--7004581222  57221813377--7004581222 
## [22] 57769896800--57054490100 57769896800--57774134300 57769896800--57760555100
## + ... omitted several edges
dim(mat_g2_incidence_to_1)
## [1] 727 727
g<-graph.adjacency(mat_g2_incidence_to_1, mode = "undirected", weighted = TRUE, diag=F)
g
## IGRAPH c6c5985 UNW- 727 2535 -- 
## + attr: name (v/c), weight (e/n)
## + edges from c6c5985 (vertex names):
##  [1] 57223640712--14627618600 57223640712--56412981200 57753915200--57209094353
##  [4] 58288848400--58289105500 58288848400--58289499100 58288848400--57570827800
##  [7] 58288848400--57200371657 58288848400--6508378209  58288848400--58289499200
## [10] 58288848400--58289499300 58288848400--58288979300 58288848400--57201813646
## [13] 58061860400--58241995800 58061860400--57204101861 57301216200--57200151370
## [16] 50262958000--7005495251  50262958000--57220804469 57221813377--57063266900
## [19] 57221813377--7004581222  57769896800--57054490100 57769896800--57774134300
## [22] 57769896800--57760555100 57769896800--57760448100 57769896800--37120645800
## + ... omitted several edges
#Interactive Visualization
V(g)$label<-V(g)$name
V(g)$name<-1:length(V(g)) 
g
## IGRAPH c6c5985 UNW- 727 2535 -- 
## + attr: name (v/n), label (v/c), weight (e/n)
## + edges from c6c5985 (vertex names):
##  [1]  1--176  1--329  2--177  3--178  3--330  3--443  3--527  3--580  3--618
## [10]  3--641  3--652  3--662  5--179  5--195  6--180  7--181  7--331  8--182
## [19]  8--332  9--183  9--333  9--444  9--528  9--581  9--619 11--184 11--334
## [28] 12--185 13--186 13--335 14--187 14--336 14--445 15--188 15--337 15--446
## [37] 16--189 16--338 16--447 16--529 16--582 17--190 17--339 17--448 18--191
## [46] 18--340 18--449 18--530 18--583 18--620 18--642 18--653 18--663 18--671
## [55] 18--678 18--683 18--689 18--693 18--696 18--698 18--700 18--702 18--704
## [64] 18--706 19-- 37 19--192 21--193 22--194 23--196 23--341 23--450 23--531
## + ... omitted several edges
#checkpoint

############
#In HTML visualizations (like NetworkD3) we need two datasets, one for links, another for nodes attributes.
############

#Gets edgelist from graph, also any other attribute at the edge level to be included in the mapping
links<-as.data.frame(cbind(get.edgelist(g), E(g)$weight))

#Needs to be numeric
links$V1<-as.numeric(as.character(links$V1))

links$V2<-as.numeric(as.character(links$V2))
str(links)
## 'data.frame':    2535 obs. of  3 variables:
##  $ V1: num  1 1 2 3 3 3 3 3 3 3 ...
##  $ V2: num  176 329 177 178 330 443 527 580 618 641 ...
##  $ V3: num  1 1 1 1 1 1 1 1 1 1 ...
links$V3<-round(as.numeric(as.character(links$V3)),3)
head(links)
##   V1  V2 V3
## 1  1 176  1
## 2  1 329  1
## 3  2 177  1
## 4  3 178  1
## 5  3 330  1
## 6  3 443  1
colnames(links)<-c("source","target","value")

#Counts begin at zero in computer programming
links[,1:2]<-(links[,1:2]-1)

dim(links)
## [1] 2535    3
V(g)$pub_count<- pub_count$Freq[match(V(g)$label, pub_count$Var1)]
V(g)$author_name <- df_authorid_authorname_unlisted$names[match(df_authorid_authorname_unlisted$id, V(g)$label)]
V(g)$size<- cent$bet[match(V(g)$label, cent$name)]
V(g)$eig <- cent$eig[match(V(g)$label, cent$name)]
V(g)$deg <- cent$degree[match(V(g)$label, cent$name)]

summary(V(g)$size)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.000000 0.000000 0.000000 0.001501 0.000000 1.000000
nodes <- data.frame(name= c(paste("ID: ", V(g)$label[1:i],
                                  ", Pub Count: ", V(g)$pub_count, 
                                  ", Name: ", V(g)$author_name, 
                                  sep="")),
                    size=abs(V(g)$size),
                    EV_cent=abs(V(g)$eig),
                    deg_cent=abs(V(g)$deg)
)
nodes$name<-as.character(nodes$name)
head(nodes);tail(nodes)
##                                                  name       size EV_cent
## 1     ID: 57223640712, Pub Count: 1, Name: aattouri i 0.00000000       0
## 2     ID: 57753915200, Pub Count: 1, Name: almuhana h 0.00000000       0
## 3  ID: 58288848400, Pub Count: 1, Name: leidinger m.l 0.00000000       0
## 4  ID: 58258344100, Pub Count: 1, Name: almelhes s.a. 0.00000000       0
## 5 ID: 58061860400, Pub Count: 2, Name: moulieswaran n 0.02797203       0
## 6    ID: 57301216200, Pub Count: 1, Name: chaudhury s 0.00000000       0
##   deg_cent
## 1        1
## 2        1
## 3        1
## 4        1
## 5        2
## 6        1
##                                                   name size EV_cent deg_cent
## 722 ID: 57871605700, Pub Count: 1, Name: triefenbach f    0       1        1
## 723         ID: 57787054200, Pub Count: 1, Name: wei p    0       1        1
## 724          ID: 57226017336, Pub Count: 1, Name: yu h    0       1        1
## 725       ID: 56393534400, Pub Count: 1, Name: zheng s    0       1        1
## 726         ID: 15060858000, Pub Count: 1, Name: tur g    0       1        1
## 727  ID: 35607445600, Pub Count: 1, Name: natarajan p.    0       1        1
nodes$group<-NA
nodes$pub_count <- as.numeric(V(g)$pub_count)
nodes$group <- cut(nodes$pub_count, c(1, 2, max(nodes$pub_count) + 1), right = TRUE, labels = FALSE)
table(is.na(nodes$group))
## 
## FALSE  TRUE 
##    10   717
table(nodes$group)
## 
##  1 
## 10
head(nodes[is.na(nodes$group),],20)
##                                                       name size EV_cent
## 1          ID: 57223640712, Pub Count: 1, Name: aattouri i    0       0
## 2          ID: 57753915200, Pub Count: 1, Name: almuhana h    0       0
## 3       ID: 58288848400, Pub Count: 1, Name: leidinger m.l    0       0
## 4       ID: 58258344100, Pub Count: 1, Name: almelhes s.a.    0       0
## 6         ID: 57301216200, Pub Count: 1, Name: chaudhury s    0       0
## 7        ID: 50262958000, Pub Count: 1, Name: sankaran g.c    0       0
## 9               ID: 57769896800, Pub Count: 1, Name: liu x    0       0
## 10          ID: 41561548400, Pub Count: 1, Name: hockly n.    0       0
## 11            ID: 57222072140, Pub Count: 1, Name: rad h.s    0       0
## 12 ID: 58205160300, Pub Count: 1, Name: hilao-valencia p.m    0       0
## 13           ID: 57191156064, Pub Count: 1, Name: ouared a    0       0
## 14 ID: 58158727000, Pub Count: 1, Name: sargazi moghadam t    0       0
## 15            ID: 57209902552, Pub Count: 1, Name: singh a    0       0
## 16          ID: 57211158344, Pub Count: 1, Name: havinga i    0       0
## 17          ID: 57220870257, Pub Count: 1, Name: barbosa b    0       0
## 18         ID: 58127773400, Pub Count: 1, Name: yang l.w.y    0       0
## 20         ID: 7006806419, Pub Count: 1, Name: kralik j.d.    0       0
## 21          ID: 57225105038, Pub Count: 1, Name: mahdi a.y    0       0
## 22            ID: 14039593800, Pub Count: 1, Name: mouti s    0       0
## 23           ID: 57204435819, Pub Count: 1, Name: olenyi t    0       0
##    deg_cent group pub_count
## 1         1    NA         1
## 2         1    NA         1
## 3         1    NA         1
## 4         1    NA         1
## 6         1    NA         1
## 7         1    NA         1
## 9         1    NA         1
## 10        1    NA         1
## 11        1    NA         1
## 12        1    NA         1
## 13        1    NA         1
## 14        1    NA         1
## 15        1    NA         1
## 16        1    NA         1
## 17        1    NA         1
## 18        1    NA         1
## 20        1    NA         1
## 21        1    NA         1
## 22        1    NA         1
## 23        1    NA         1
nodes$group<-ifelse(is.na(nodes$group), "Published 1 article", ifelse(nodes$group==1, "Published 2 articles", "Published 1 article"))
counts<-data.frame(table(nodes$group))
counts
##                   Var1 Freq
## 1  Published 1 article  717
## 2 Published 2 articles   10
counts$labels <- paste(counts$Var1, ", N= ", counts$Freq, sep="")
nodes$groups <- counts$labels[match(nodes$group, counts$Var1)] 
head(nodes)
##                                                  name       size EV_cent
## 1     ID: 57223640712, Pub Count: 1, Name: aattouri i 0.00000000       0
## 2     ID: 57753915200, Pub Count: 1, Name: almuhana h 0.00000000       0
## 3  ID: 58288848400, Pub Count: 1, Name: leidinger m.l 0.00000000       0
## 4  ID: 58258344100, Pub Count: 1, Name: almelhes s.a. 0.00000000       0
## 5 ID: 58061860400, Pub Count: 2, Name: moulieswaran n 0.02797203       0
## 6    ID: 57301216200, Pub Count: 1, Name: chaudhury s 0.00000000       0
##   deg_cent                group pub_count                      groups
## 1        1  Published 1 article         1 Published 1 article, N= 717
## 2        1  Published 1 article         1 Published 1 article, N= 717
## 3        1  Published 1 article         1 Published 1 article, N= 717
## 4        1  Published 1 article         1 Published 1 article, N= 717
## 5        2 Published 2 articles         2 Published 2 articles, N= 10
## 6        1  Published 1 article         1 Published 1 article, N= 717
colnames(nodes)
## [1] "name"      "size"      "EV_cent"   "deg_cent"  "group"     "pub_count"
## [7] "groups"
colnames(links)
## [1] "source" "target" "value"
library(networkD3)
library(magrittr)
library(htmlwidgets)
## 
## Attaching package: 'htmlwidgets'
## The following object is masked from 'package:networkD3':
## 
##     JS
library(htmltools)
netviz<-forceNetwork(Links = links, Nodes = nodes,
                     Source = 'source', Target = 'target',
                     NodeID = 'name',
                     Group = "groups",
                     charge = -30, # node repulsion
                     linkDistance = JS("function(d) { return d.linkDistance; }"),
                     linkWidth = JS("function(d) { return Math.sqrt(d.value)*2; }"),
                     opacity = 0.8,
                     Nodesize = 'size', 
                     radiusCalculation = JS("Math.sqrt(d.nodesize*30)+4"),
                     zoom = T, 
                     fontSize=14,
                     bounded= F,
                     legend= TRUE,
                     linkColour = ifelse(links$value == 1, "#CCFFFF", ifelse(links$value == 2, "#e3eaa7", "#abb2b9 ")),
                     colourScale = JS("d3.scaleOrdinal(d3.schemeCategory10)"))

HTMLaddons <- 
  "function(el, x) { 
d3.select('body').style('background-color', ' #212f3d ')
d3.selectAll('.legend text').style('fill', 'white') 
 d3.selectAll('.link').append('svg:title')
 #change only the title
      .text(function(d) { return 'Grade course: ' + d.value + ', Campus: ' + d.campus ; })
  var options = x.options;
  var svg = d3.select(el).select('svg')
  var node = svg.selectAll('.node');
  var link = svg.selectAll('link');
  var mouseout = d3.selectAll('.node').on('mouseout');
  function nodeSize(d) {
    if (options.nodesize) {
      return eval(options.radiusCalculation);
    } else {
      return 6;
    }
  }

  
d3.selectAll('.node').on('click', onclick)

  function onclick(d) {
    if (d3.select(this).on('mouseout') == mouseout) {
      d3.select(this).on('mouseout', mouseout_clicked);
    } else {
      d3.select(this).on('mouseout', mouseout);
    }
  }

  function mouseout_clicked(d) {
    node.style('opacity', +options.opacity);
    link.style('opacity', +options.opacity);

    d3.select(this).select('circle').transition()
      .duration(750)
      .attr('r', function(d){return nodeSize(d);});
    d3.select(this).select('text').transition()
    
      .duration(1250)
      .attr('x', 0)
      .style('font', options.fontSize + 'px ');
  }

}
"
netviz$x$links$linkDistance <- (1/links$value)*1500
netviz$x$links$campus <- links$campus
onRender(netviz, HTMLaddons)