##------ Aug 2, 2010 8:35:47 PM ------## > setwd("Y:\\cgi-bin\\sna_drupal\\sna_R_labs\\output\\lab_3") > ####################################### > # LAB 3: Clusters, Factions and Cores # > ####################################### > > # NOTE: if you have trouble because some packages are not installed, > # see lab 1 for instructions on how to install all necessary packages. > > > ############################################################## > # > # Lab 3 > # > # The purpose of this lab is to identify friendship groups > # or cliques using different methods, to discern the best > # fitting clique structure, and to develop clique-models of > # task and social interaction patterns. > # > ############################################################## > > ### > #1. SETUP > ### > > # For this lab, we'll use a few different packages. "sna" is a > # social-network-analysis package similar to igraph, but with some > # different and useful functions. "cluster" is a generic cluster- > # analysis package with applications beyond the social-network > # context. "animation" is used, not surprisingly, to produce > # animations. > library('igraph') > library('sna') Tools for Social Network Analysis Version 2.0-1 created on 2009-06-07. copyright (c) 2005, Carter T. Butts, University of California-Irvine Type help(package="sna") to get started. Attaching package: 'sna' The following object(s) are masked _by_ .GlobalEnv : reachability The following object(s) are masked from package:igraph : %c%, betweenness, bonpow, closeness, degree, dyad.census, evcent, is.connected, neighborhood, triad.census > library('cluster') > library('animation') Loading required package: MASS > > > ### > #2. LOADING AND FORMATTING DATA > ### > > # We'll use the NetData package to load the data this time around: > > data(studentnets.M182, package = "NetData") > > # For this lab, we'll use three files from Student Nets M182 Sem > # 2. FRN.DAT shows self-reported friendship ties, SSL.DAT shows > # observed social interactions, and TSL.DAT shows observed > # task interactions. > # > # All of the files should be in the following format: > # 1 1 0.000000 > # 1 2 2.000000 > # 1 3 1.000000 > # where the first line is the ego, the second line is the alter, > # and the third line is an integer or floating-point number > # greater than or equal to zero showing the strength of the > # association for the given two vertices. > > # Reduce to non-zero edges and build a graph object > m182_full_nonzero_edges <- subset(m182_full_data_frame, (friend_tie > 0 | social_tie > 0 | task_tie > 0)) > head(m182_full_nonzero_edges) ego alter friend_tie social_tie task_tie 5 1 5 0 1.20 0.30 8 1 8 0 0.15 0.00 9 1 9 0 2.85 0.30 10 1 10 0 6.45 0.30 11 1 11 0 0.30 0.00 12 1 12 0 1.95 0.15 > > m182_full <- graph.data.frame(m182_full_nonzero_edges) > summary(m182_full) Vertices: 16 Edges: 144 Directed: TRUE No graph attributes. Vertex attributes: name. Edge attributes: friend_tie, social_tie, task_tie. > > # Create sub-graphs based on edge attributes > m182_friend <- delete.edges(m182_full, E(m182_full)[get.edge.attribute(m182_full,name = "friend_tie")==0]) > > m182_social <- delete.edges(m182_full, E(m182_full)[get.edge.attribute(m182_full,name = "social_tie")==0]) > summary(m182_social) Vertices: 16 Edges: 129 Directed: TRUE No graph attributes. Vertex attributes: name. Edge attributes: friend_tie, social_tie, task_tie. > > m182_task <- delete.edges(m182_full, E(m182_full)[get.edge.attribute(m182_full,name = "task_tie")==0]) > summary(m182_task) Vertices: 16 Edges: 88 Directed: TRUE No graph attributes. Vertex attributes: name. Edge attributes: friend_tie, social_tie, task_tie. > > # Look at the plots for each sub-graph > friend_layout <- layout.fruchterman.reingold(m182_friend) > plot(m182_friend, layout=friend_layout, edge.arrow.size=.5) > > social_layout <- layout.fruchterman.reingold(m182_social) > plot(m182_social, layout=social_layout, edge.arrow.size=.5) > > task_layout <- layout.fruchterman.reingold(m182_task) > plot(m182_task, layout=task_layout, edge.arrow.size=.5) > > > ### > # 3. COMMUNITY DETECTION > ### > > # We'll use the friend sub-graph as the basis for our community > # detection methods. For clarity and simplicity, we'll set the > # network to undirected and remove isolated vertices. Comparing > # m182_friend before and after these operations, you'll notice > # that the number of edges decreases as reciprocated directed ties > # are consolidated into single undirected ties, and the number of > # vertices decreases as isolates are removed. > m182_friend_und <- as.undirected(m182_friend, mode='collapse') > m182_friend_no_iso <- delete.vertices(m182_friend_und, V(m182_friend_und)[degree(m182_friend_und)==0]) > summary(m182_friend) Vertices: 16 Edges: 62 Directed: TRUE No graph attributes. Vertex attributes: name. Edge attributes: friend_tie, social_tie, task_tie. > summary(m182_friend_no_iso) Vertices: 14 Edges: 42 Directed: FALSE No graph attributes. Vertex attributes: name. No edge attributes. > > # There are many different ways to detect communities. In this > # lab, we'll use three: hierarchical NetCluster, walktrap, and > # edge-betweenness. As you use them, consider how they portray > # clusters and consider which one(s) afford a sensible view of > # the social world as cohesively organized. > > > ### > # 3A. COMMUNITY DETECTION: HIERARCHICAL CLUSTERING > ### > > # This is a generic form of cluster analysis that seeks to form > # clusters based on a given distance metric between two nodes. For > # this lab, we'll use the default settings of the dist() and > # hclust() functions, which results in clusters being constructed > # based on Euclidean distance and complete linkages between > # clusters. Other options exist for those who want to do additional > # exploring. > > # The first step is to coerce our data into an adjacency matrix. > m182_friend_matrix <- get.adjacency(m182_friend_no_iso) > m182_friend_matrix 1 2 3 5 6 7 8 9 10 11 12 13 14 15 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 2 1 0 0 0 0 1 1 0 0 0 0 1 1 0 3 0 0 0 1 1 0 0 1 0 1 0 0 1 1 5 1 0 1 0 1 0 1 0 1 1 0 0 0 0 6 1 0 1 1 0 1 0 0 1 1 1 0 0 0 7 0 1 0 0 1 0 1 0 0 0 0 1 1 1 8 0 1 0 1 0 1 0 0 0 0 0 1 1 1 9 1 0 1 0 0 0 0 0 1 0 1 0 0 1 10 1 0 0 1 1 0 0 1 0 1 1 0 0 1 11 1 0 1 1 1 0 0 0 1 0 0 0 0 0 12 1 0 0 0 1 0 0 1 1 0 0 0 1 1 13 0 1 0 0 0 1 1 0 0 0 0 0 1 0 14 0 1 1 0 0 1 1 0 0 0 1 1 0 0 15 1 0 1 0 0 1 1 1 1 0 1 0 0 0 > > # Now we can use the built-in function dist() to compute a > # "distance matrix" showing how structurally dissimilar each > # vertex is to each other vertex. Note that higher values indicate > # greater dissimilarity. > m182_friend_dist <- dist(m182_friend_matrix) > m182_friend_dist 1 2 3 5 6 7 8 9 2 3.605551 3 2.000000 3.000000 5 2.828427 2.645751 2.828427 6 2.645751 2.828427 3.000000 2.236068 7 2.828427 2.236068 2.449490 2.828427 3.605551 8 2.828427 2.236068 2.449490 3.464102 3.000000 2.000000 9 2.645751 2.828427 3.000000 2.236068 2.000000 3.000000 3.000000 10 1.732051 3.162278 1.732051 2.645751 2.449490 3.000000 3.000000 2.449490 11 2.645751 2.828427 2.645751 1.732051 2.000000 3.000000 3.000000 2.000000 12 2.449490 2.645751 2.000000 2.449490 3.000000 2.449490 2.828427 2.236068 13 3.162278 1.732051 2.828427 2.828427 3.000000 2.000000 2.000000 3.000000 14 3.162278 2.236068 3.464102 2.828427 2.645751 2.449490 2.449490 2.645751 15 3.000000 2.449490 3.316625 2.236068 2.000000 3.316625 3.316625 2.000000 10 11 12 13 14 2 3 5 6 7 8 9 10 11 2.449490 12 2.236068 2.236068 13 3.316625 3.000000 2.828427 14 3.316625 3.000000 3.464102 2.000000 15 2.828427 2.449490 2.645751 2.645751 2.236068 > > # hclust() performs a hierarchical agglomerative NetCluster > # operation based on the values in the dissimilarity matrix > # yielded by dist() above. > m182_friend_hclust <- hclust(m182_friend_dist) > > # The default way to visualize clusters is a tree structure called > # a dendrogram. The y-axis values on the dendrogram show the > # Euclidean distances between nodes. Since the hclust() default > # is complete linkage, the distances between one or more nodes and > # a cluster of nodes is the Euclidean distance of the two nodes > # farthest apart. > # QQQ WHAT DO THE VALUES ON THE Y AXIS LABELED HEIGHT?? ARE THEY EUCLIDEAN DISTANCES? > # MN_QQQ DONE > plot(m182_friend_hclust) > > # Question #1 - How many clusters would you select here and why? > > ### > # 3B. COMMUNITY DETECTION: WALKTRAP > ### > > # This algorithm detects communities through a series of short > # random walks, with the idea that the vertices encountered on > # any given random walk are more likely to be within a community > # than not. The algorithm initially treats all nodes as > # communities of their own, then merges them into larger > # communities, and these into still larger communities, and so on. > # In each step a new community is created from two other > # communities, and its ID will be one larger than the largest > # community ID so far. This means that before the first merge we > # have n communities (the number of vertices in the graph) > # numbered from zero to n-1. The first merge creates community n, > # the second community n+1, etc. This merge history is returned by > # the function. > friend_comm_wt <- walktrap.community(m182_friend_no_iso, steps=200,modularity=TRUE,labels=TRUE) > friend_comm_wt $merges [,1] [,2] [1,] 4 8 [2,] 0 3 [3,] 6 11 [4,] 10 13 [5,] 7 15 [6,] 9 14 [7,] 12 16 [8,] 2 17 [9,] 18 19 [10,] 5 21 [11,] 1 23 [12,] 22 24 [13,] 20 25 $modularity [1] 0.000000000 -0.063492063 -0.053287982 -0.036281179 -0.024376417 [6] -0.020408163 0.007369615 0.037981859 0.039682540 0.104024943 [11] 0.095521542 0.083900227 0.070294785 0.000000000 $labels [1] "1" "2" "3" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" attr(,"class") [1] "igraph.walktrap" > > # As with hierarchical NetCluster above, we can also visualize > # the clusters generated by walktrap as a dendrogram (but note that > # the clusters themselves may be different). Here, the y-axis > # reflects the distance metric used by the walktrap algorithm; for > # more on this, see Pascal Pons, Matthieu Latapy: Computing communities > # in large networks using random walks, http://arxiv.org/abs/physics/0512106. > # QQQ WHAT DO THE VALUES ON THE Y AXIS MEAN?? > # MN_QQQ LOOKS LIKE THEY'RE THE DISTANCE METRIC FOR THE WALKTRAP ALGORITHM, WHICH IS DESCRIBED IN THE PONS & LATAPY PAPER DESCRIBED ABOVE. PRETTY SURE THIS IS RIGHT BUT IT WOULD BE GOOD FOR SOMEONE ELSE TO CHECK THIS. > friend_comm_dend <- as.dendrogram(friend_comm_wt, use.modularity=TRUE) > plot(friend_comm_dend) > > # Question #2 - How many clusters would you select here and why? > > ### > # 3C. COMMUNITY DETECTION: EDGE BETWEENNESS METHOD > ### > > # The edge-betweenness score of an edge measures the number of > # shortest paths from one vertex to another that go through it. > # The idea of the edge-betweenness based community structure > # detection is that it is likely that edges connecting separate > # cluster have high edge-betweenness, as all the shortest paths > # from one cluster to another must traverse through them. So if we > # iteratively remove the edge with the highest edge-betweenness > # score we will get a hierarchical map of the communities in the > # graph. > # > # The following function will find the betweenness for each > # vertex. > friend_comm_eb <- edge.betweenness.community(m182_friend_no_iso) > friend_comm_eb $removed.edges [1] 0 22 19 16 39 29 32 17 14 25 36 5 1 20 2 23 3 4 6 7 8 9 10 11 12 [26] 13 15 18 21 24 26 27 28 30 31 33 34 35 37 38 40 41 $edge.betweenness [1] 8.616667 8.666667 11.092857 14.333333 16.666667 22.500000 45.000000 [8] 2.650000 3.916667 3.619048 3.333333 5.266667 5.000000 7.500000 [15] 10.000000 20.000000 1.000000 1.333333 2.000000 4.000000 1.000000 [22] 1.333333 2.000000 4.000000 1.000000 1.500000 3.000000 1.000000 [29] 2.000000 1.000000 1.000000 1.500000 3.000000 1.000000 2.000000 [36] 1.000000 1.500000 3.000000 1.000000 2.000000 1.000000 1.000000 $merges [,1] [,2] [1,] 11 12 [2,] 10 13 [3,] 8 15 [4,] 7 16 [5,] 6 14 [6,] 5 18 [7,] 4 9 [8,] 3 20 [9,] 2 21 [10,] 1 19 [11,] 0 17 [12,] 22 24 [13,] 23 25 $bridges [1] 42 41 40 38 35 33 30 29 27 24 20 16 7 $labels [1] "1" "2" "3" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" attr(,"class") [1] "igraph.ebc" > > # This process also lends itself to visualization as a dendrogram. > # The y-axis reflects the distance metric used by the edge betweennes > # algorithm; for more on this, see M Newman and M Girvan: Finding and > # evaluating community structure in networks, Physical Review E 69, 026113 > # (2004), http://arxiv.org/abs/cond-mat/0308217. > # QQQ WHAT DO THE VALUES ON THE Y AXIS MEAN?? DO THEY REFER TO MAX EDGE BETWEENNESS? > # MN_QQQ AS WITH WALKTRAP, LOOKS LIKE THE DISTANCE METRIC USED BY THE ALGORITHM AND DESCRIBED IN THE NEWMAN & GIRVAN PAPER... BUT WOULD BE GOOD FOR SOMEONE TO DOUBLE-CHECK THIS. > plot(as.dendrogram(friend_comm_eb)) > > # Question #3 - How many clusters would you select here and why? > > # The following code produces an animation of the edge-betweeness > # process. It's easiest to run all of this code at once. The > # result is a set of .png files that will be saved to the default > # working directory (or the working directory specified by setwd(), > # if any). Note that the code may throw an error, but this doesn't > # necessarily mean it didn't work; check the appropriate folder > # for the .png files to see. Highlight all the .png files and open > # them in Preview as a slideshow. > > # *** START ANIMATION CODE *** > > jitter.ani <-function(x, g){ + + l <- layout.kamada.kawai(g, niter=1000) + ebc <- edge.betweenness.community(g) + + colbar <- rainbow(6) + colbar2 <- c(rainbow(5), rep("black",15)) + + for (i in 1:x) { + g2 <- delete.edges(g, ebc$removed.edges[seq(length=i-1)]) + eb <- edge.betweenness(g2) + cl <- clusters(g2)$membership + q <- modularity(g, cl) + E(g2)$color <- "grey" + E(g2)[ order(eb, decreasing=TRUE)[1:5]-1 ]$color <- colbar2[1:5] + + E(g2)$width <- 1 + E(g2)[ color != "grey" ]$width <- 2 + + plot(g2, layout=l, vertex.size=12, + edge.label.color="red", vertex.color=colbar[cl+2], + edge.label.font=2) + title(main=paste("Q=", round(q,3)), font=2) + ty <- seq(1,by=-strheight("1")*1.5, length=20) + text(-1.3, ty, adj=c(0,0.5), round(sort(eb, dec=TRUE)[1:20],2), + col=colbar2, font=2) + } + } > > saveMovie(jitter.ani(20, m182_friend_no_iso), interval = 0.5, outdir = getwd()) Executing: convert -delay 50 -loop 0 Rplot*.png movie.gif Movie has been created at: Y:\cgi-bin\sna_drupal\sna_R_labs\output\lab_3\movie.gif > > # *** END ANIMATION CODE *** > > > # Now we'll decide on an optimum number of communities for this > # network. All of the community methods above allow us to iterate > # through different numbers of communities and judge how well > # correlated a given idealized community structure is with the > # observed network. > # > # We'll start by getting an adjacency matrix based on the network > # with isolates removed. > friend_adj_mat_no_iso <- get.adjacency(m182_friend_no_iso, binary=TRUE) > friend_adj_mat_no_iso 1 2 3 5 6 7 8 9 10 11 12 13 14 15 1 0 1 0 1 1 0 0 1 1 1 1 0 0 1 2 1 0 0 0 0 1 1 0 0 0 0 1 1 0 3 0 0 0 1 1 0 0 1 0 1 0 0 1 1 5 1 0 1 0 1 0 1 0 1 1 0 0 0 0 6 1 0 1 1 0 1 0 0 1 1 1 0 0 0 7 0 1 0 0 1 0 1 0 0 0 0 1 1 1 8 0 1 0 1 0 1 0 0 0 0 0 1 1 1 9 1 0 1 0 0 0 0 0 1 0 1 0 0 1 10 1 0 0 1 1 0 0 1 0 1 1 0 0 1 11 1 0 1 1 1 0 0 0 1 0 0 0 0 0 12 1 0 0 0 1 0 0 1 1 0 0 0 1 1 13 0 1 0 0 0 1 1 0 0 0 0 0 1 0 14 0 1 1 0 0 1 1 0 0 0 1 1 0 0 15 1 0 1 0 0 1 1 1 1 0 1 0 0 0 > num_vertices = nrow(friend_adj_mat_no_iso) > num_vertices [1] 14 > > # Next, we'll derive a set of idealized community structures > # at each possible number of communities. We can correlate each > # of these structures with the observed community and store > # the correlation statistics in a vector. > # > # This code loops through each possible number of communities that > # can be derived using the edge-betweenness method, but it could > # readily be applied to the other clustering methods above. For each > # number of communities, it prints out an adjacency matrix with 0s > # indicating that the row and column vertices do not share a > # community and 1s indicating that they do. > # > # Thus, the first iteration returns 14 communities, one for each > # vertex, and an adjacency matrix of all 0s. The last iteration > # returns a single community comprised of all vertices, and an > # adjacency matrix of all 1s (except on the diagonal). > # > # Meanwhile, we can correlate each community structure with the > # observed community to generate a list of ideal-observed > # correlations. > ideal_observed_cors = vector() > for (i in 0:(num_vertices-1)) { + num_comms = (num_vertices - i) + cat('number of communities: ', num_comms, '\n') + community <- community.to.membership(m182_friend_no_iso, friend_comm_eb$merges, i) + print(community) + idealized_comm_mat <- matrix(nrow=num_vertices, ncol=num_vertices) + + for (m in 1:num_vertices) { + for (n in 1:num_vertices) { + if (m==n) { + idealized_comm_mat[m,n] = 0 + } else if (community$membership[m] == community$membership[n]) { + idealized_comm_mat[m,n] = 1 + } else { + idealized_comm_mat[m,n] = 0 + } + } + } + print(idealized_comm_mat) + + if (num_comms > 1 & num_comms < num_vertices) { + ideal_observed_cors <- append(ideal_observed_cors, (gcor(idealized_comm_mat, friend_adj_mat_no_iso))) + print(ideal_observed_cors[length(ideal_observed_cors)]) + } else { + ideal_observed_cors <- append(ideal_observed_cors, 0) + print('unable to calcuate correlation; setting value to 0') + } + cat('\n') + } number of communities: 14 $membership [1] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 $csize [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 0 [9,] 0 [10,] 0 [11,] 0 [12,] 0 [13,] 0 [14,] 0 [1] "unable to calcuate correlation; setting value to 0" number of communities: 13 $membership [1] 1 2 3 4 5 6 7 8 9 10 11 0 0 12 $csize [1] 2 1 1 1 1 1 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [12,] 0 0 0 0 0 0 0 0 0 0 0 0 1 [13,] 0 0 0 0 0 0 0 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 0 [9,] 0 [10,] 0 [11,] 0 [12,] 0 [13,] 0 [14,] 0 [1] 0.113855 number of communities: 12 $membership [1] 2 3 4 5 6 7 8 9 10 11 0 1 1 0 $csize [1] 2 2 1 1 1 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [12,] 0 0 0 0 0 0 0 0 0 0 0 0 1 [13,] 0 0 0 0 0 0 0 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 0 0 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 0 [9,] 0 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.1619174 number of communities: 11 $membership [1] 2 3 4 5 6 7 8 9 0 10 0 1 1 0 $csize [1] 3 2 1 1 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [9,] 0 0 0 0 0 0 0 0 0 0 1 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 0 1 0 0 0 0 [12,] 0 0 0 0 0 0 0 0 0 0 0 0 1 [13,] 0 0 0 0 0 0 0 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 0 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.2316028 number of communities: 10 $membership [1] 2 3 4 5 6 7 8 0 0 9 0 1 1 0 $csize [1] 4 2 1 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 0 0 0 0 0 0 0 1 [13,] 0 0 0 0 0 0 0 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.3118048 number of communities: 9 $membership [1] 2 3 4 5 6 7 0 1 1 8 1 0 0 1 $csize [1] 3 4 1 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [7,] 0 0 0 0 0 0 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 0 1 0 0 0 0 0 1 [13,] 0 0 0 0 0 0 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.3578390 number of communities: 8 $membership [1] 2 3 4 5 6 0 0 1 1 7 1 0 0 1 $csize [1] 4 4 1 1 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [6,] 0 0 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 0 0 0 0 1 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 0 0 0 0 1 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.4209693 number of communities: 7 $membership [1] 3 4 5 6 0 1 1 2 2 0 2 1 1 2 $csize [1] 2 4 4 1 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [5,] 0 0 0 0 0 0 0 0 0 1 0 0 0 [6,] 0 0 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 0 0 0 0 1 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 0 0 1 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 0 0 0 0 1 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.4409586 number of communities: 6 $membership [1] 3 4 5 0 0 1 1 2 2 0 2 1 1 2 $csize [1] 3 4 4 1 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [4,] 0 0 0 0 1 0 0 0 0 1 0 0 0 [5,] 0 0 0 1 0 0 0 0 0 1 0 0 0 [6,] 0 0 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 0 0 0 0 1 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 0 1 1 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 0 0 0 0 1 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.4798574 number of communities: 5 $membership [1] 3 4 0 0 0 1 1 2 2 0 2 1 1 2 $csize [1] 4 4 4 1 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [3,] 0 0 0 1 1 0 0 0 0 1 0 0 0 [4,] 0 0 1 0 1 0 0 0 0 1 0 0 0 [5,] 0 0 1 1 0 0 0 0 0 1 0 0 0 [6,] 0 0 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 0 0 0 0 1 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 1 1 1 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 0 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 0 0 0 0 1 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.5363499 number of communities: 4 $membership [1] 3 0 1 1 1 0 0 2 2 1 2 0 0 2 $csize [1] 5 4 4 1 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 0 0 0 0 0 0 [2,] 0 0 0 0 0 1 1 0 0 0 0 1 1 [3,] 0 0 0 1 1 0 0 0 0 1 0 0 0 [4,] 0 0 1 0 1 0 0 0 0 1 0 0 0 [5,] 0 0 1 1 0 0 0 0 0 1 0 0 0 [6,] 0 1 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 1 0 0 0 1 0 0 0 0 0 1 1 [8,] 0 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 0 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 1 1 1 0 0 0 0 0 0 0 0 [11,] 0 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 1 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 1 0 0 0 1 1 0 0 0 0 1 0 [14,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 0 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.6099022 number of communities: 3 $membership [1] 0 1 2 2 2 1 1 0 0 2 0 1 1 0 $csize [1] 5 5 4 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 0 0 0 0 0 1 1 0 1 0 0 [2,] 0 0 0 0 0 1 1 0 0 0 0 1 1 [3,] 0 0 0 1 1 0 0 0 0 1 0 0 0 [4,] 0 0 1 0 1 0 0 0 0 1 0 0 0 [5,] 0 0 1 1 0 0 0 0 0 1 0 0 0 [6,] 0 1 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 1 0 0 0 1 0 0 0 0 0 1 1 [8,] 1 0 0 0 0 0 0 0 1 0 1 0 0 [9,] 1 0 0 0 0 0 0 1 0 0 1 0 0 [10,] 0 0 1 1 1 0 0 0 0 0 0 0 0 [11,] 1 0 0 0 0 0 0 1 1 0 0 0 0 [12,] 0 1 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 1 0 0 0 1 1 0 0 0 0 1 0 [14,] 1 0 0 0 0 0 0 1 1 0 1 0 0 [,14] [1,] 1 [2,] 0 [3,] 0 [4,] 0 [5,] 0 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 0 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.68313 number of communities: 2 $membership [1] 0 1 0 0 0 1 1 0 0 0 0 1 1 0 $csize [1] 9 5 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 0 1 1 1 0 0 1 1 1 1 0 0 [2,] 0 0 0 0 0 1 1 0 0 0 0 1 1 [3,] 1 0 0 1 1 0 0 1 1 1 1 0 0 [4,] 1 0 1 0 1 0 0 1 1 1 1 0 0 [5,] 1 0 1 1 0 0 0 1 1 1 1 0 0 [6,] 0 1 0 0 0 0 1 0 0 0 0 1 1 [7,] 0 1 0 0 0 1 0 0 0 0 0 1 1 [8,] 1 0 1 1 1 0 0 0 1 1 1 0 0 [9,] 1 0 1 1 1 0 0 1 0 1 1 0 0 [10,] 1 0 1 1 1 0 0 1 1 0 1 0 0 [11,] 1 0 1 1 1 0 0 1 1 1 0 0 0 [12,] 0 1 0 0 0 1 1 0 0 0 0 0 1 [13,] 0 1 0 0 0 1 1 0 0 0 0 1 0 [14,] 1 0 1 1 1 0 0 1 1 1 1 0 0 [,14] [1,] 1 [2,] 0 [3,] 1 [4,] 1 [5,] 1 [6,] 0 [7,] 0 [8,] 1 [9,] 1 [10,] 1 [11,] 1 [12,] 0 [13,] 0 [14,] 0 [1] 0.6070762 number of communities: 1 $membership [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $csize [1] 14 [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [1,] 0 1 1 1 1 1 1 1 1 1 1 1 1 [2,] 1 0 1 1 1 1 1 1 1 1 1 1 1 [3,] 1 1 0 1 1 1 1 1 1 1 1 1 1 [4,] 1 1 1 0 1 1 1 1 1 1 1 1 1 [5,] 1 1 1 1 0 1 1 1 1 1 1 1 1 [6,] 1 1 1 1 1 0 1 1 1 1 1 1 1 [7,] 1 1 1 1 1 1 0 1 1 1 1 1 1 [8,] 1 1 1 1 1 1 1 0 1 1 1 1 1 [9,] 1 1 1 1 1 1 1 1 0 1 1 1 1 [10,] 1 1 1 1 1 1 1 1 1 0 1 1 1 [11,] 1 1 1 1 1 1 1 1 1 1 0 1 1 [12,] 1 1 1 1 1 1 1 1 1 1 1 0 1 [13,] 1 1 1 1 1 1 1 1 1 1 1 1 0 [14,] 1 1 1 1 1 1 1 1 1 1 1 1 1 [,14] [1,] 1 [2,] 1 [3,] 1 [4,] 1 [5,] 1 [6,] 1 [7,] 1 [8,] 1 [9,] 1 [10,] 1 [11,] 1 [12,] 1 [13,] 1 [14,] 0 [1] "unable to calcuate correlation; setting value to 0" > ideal_observed_cors <- rev(ideal_observed_cors) > ideal_observed_cors [1] 0.0000000 0.6070762 0.6831301 0.6099022 0.5363499 0.4798574 0.4409586 [8] 0.4209693 0.3578390 0.3118048 0.2316028 0.1619174 0.1138550 0.0000000 > > # QQQ HOW WOULD WE ADAPT THE ABOVE CODE TO WORK ON THE BASIC HIERARCHICAL CLUSTERING LAB? > # MN_QQQ THIS CAN BE REPLICATED FAIRLY EASILY FOR WALKTRAP BUT IT WILL TAKE A BIT MORE EFFORT TO MAKE IT WORK FOR HIERARCHICAL CLUSTERING. HOW IMPORTANT IS THAT FUNCTIONALITY? > # We can then plot the list of correlations to determine the > # optimum number of communities for this particular network. > plot(ideal_observed_cors) > > # QUESTION #4 - Which clustering technique affords the best clique > # solution and why? What supports your claim? Why use say 4 clusters > # instead of 10? What evidence supports the claim for # of clusters? > > ### > # 4. BLOCKMODELING > ### > > # Now we'll look at some community statistics across different > # relationship networks. For all of these, we'll use the three > # edge-betweenness communities generated above as our basic > # social structure. We will reintroduce the two isolates we > # removed, assigning each to his/her own "community." > # > # First, we'll set a vector of communities, ordered according > # to the order of vertices. > communities <- community.to.membership(m182_friend_no_iso, friend_comm_eb$merges, num_vertices-3) > communities $membership [1] 0 1 2 2 2 1 1 0 0 2 0 1 1 0 $csize [1] 5 5 4 > > # Now we have to manually insert communities corresponding to the > # isolates. We can get their vertex ID numbers via: > friend_adj_mat_full <- get.adjacency(m182_friend, binary=TRUE) > which(degree(friend_adj_mat_full)==0) [1] 4 16 > > # Insert the isolate communities at indices 4 and 16. > # QQQ I'M CONFUSED IS THIS 4 AND 15? > # MN_QQQ NOT SURE WHERE THE CONFUSION LIES... 4 AND 16 ARE THE TWO ISOLATES (I BELIEVE 16 IS THE TEACHER). IN ORDER TO PERFORM THE COMMUNITY DETECTION ALGORITHMS, WE HAD TO REMOVE THEM FROM THE GRAPH (HENCE THE NO_ISO MATRICES ABOVE). NOW WE WANT TO RE-INSERT THEM, SO WE ASSIGNING EACH TO ITS OWN "COMMUNITY" (NUMBERED 3 AND 4) AND MANUALLY ADD THESE COMMUNITIES TO THE VECTOR OF COMMUNITIES IN THE APPROPRIATE PLACE. > communities_full <- vector() > communities_full <- append(communities_full, communities$membership[1:3]) > communities_full <- append(communities_full, 3) > communities_full <- append(communities_full, communities$membership[4:14]) > communities_full <- append(communities_full, 4) > communities_full [1] 0 1 2 3 2 2 1 1 0 0 2 0 1 1 0 4 > > # We can use this community membership vector to produce a > # blockmodel, showing the within- and between-cluster densities. > # For this we'll use the blockmodel() function in sna. Unlike > # igraph, sna counts from 1, so the first thing we need to do > # is renumber the IDs in the communities vector. > communities_full <- communities_full+1 > communities_full [1] 1 2 3 4 3 3 2 2 1 1 3 1 2 2 1 5 > > # Now we can generate the blockmodel using the adjacency matrix > # and community vector. Each "block" corresponds to a community > # listed in the communities_full vector; the values are the > # densities within and between communities. > friend_blockmodel <- blockmodel(friend_adj_mat_full, communities_full) > friend_blockmodel Network Blockmodel: Block membership: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 3 3 2 2 1 1 3 1 2 2 1 5 Reduced form blockmodel: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Block 1 Block 2 Block 3 Block 4 Block 5 Block 1 0.70 0.04 0.05 0 0 Block 2 0.12 0.90 0.10 0 0 Block 3 0.40 0.15 1.00 0 0 Block 4 0.00 0.00 0.00 NaN 0 Block 5 0.00 0.00 0.00 0 NaN > > # Compare the density values from the blockmodel to the overall > # density of the network. > graph.density(m182_friend) [1] 0.2583333 > > # Now we can repeat the blockmodel process to get within- and > # between-cluster densities for the social-interaction network, > # using the communities generated with the friends network for our > # clusters. > # > # For this data set, we want to retain the tie values. > social_adj_mat <- get.adjacency(m182_social, attr='social_tie') > social_adj_mat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 0.00 0.00 0.00 0.0 1.20 0.00 0.00 0.15 2.85 6.45 0.30 1.95 0.60 0.00 2 0.00 0.00 0.15 0.0 0.00 0.00 2.25 3.90 0.00 0.00 0.00 0.30 14.10 3.45 3 0.00 0.15 0.00 0.0 0.75 9.30 0.30 0.15 0.00 0.15 0.90 0.00 0.00 0.00 4 0.00 0.00 0.00 0.0 0.00 0.00 0.00 0.00 0.00 0.30 0.00 0.00 0.00 0.00 5 1.20 0.00 0.75 0.0 0.00 1.50 0.00 0.00 0.00 1.80 13.20 0.00 0.15 0.00 6 0.00 0.00 9.30 0.0 1.50 0.00 0.00 0.15 0.00 0.60 1.80 0.15 0.00 0.30 7 0.00 2.25 0.30 0.0 0.00 0.00 0.00 4.20 0.00 0.00 0.00 0.00 4.35 3.45 8 0.00 4.05 0.15 0.0 0.00 0.15 4.20 0.00 0.00 0.00 0.15 0.00 8.40 4.65 9 2.70 0.00 0.00 0.0 0.00 0.00 0.00 0.00 0.00 1.35 0.00 10.80 0.00 0.00 10 6.75 0.00 0.15 0.3 1.50 0.60 0.00 0.00 1.35 0.00 1.20 4.05 0.00 0.45 11 0.30 0.00 0.90 0.0 13.20 1.80 0.00 0.15 0.00 1.35 0.00 0.00 0.00 0.15 12 1.80 0.30 0.00 0.0 0.00 0.15 0.00 0.00 10.65 3.90 0.00 0.00 0.30 0.90 13 0.60 14.70 0.00 0.0 0.30 0.00 4.35 8.55 0.00 0.00 0.00 0.30 0.00 3.60 14 0.00 3.45 0.00 0.0 0.00 0.30 3.45 4.80 0.00 0.45 0.15 0.90 3.60 0.00 15 5.10 0.00 0.00 0.0 0.15 0.00 0.15 0.15 4.20 0.90 0.15 4.80 0.00 0.00 16 1.20 1.35 0.30 0.3 0.45 0.30 1.05 1.20 0.45 1.20 0.30 1.35 1.35 1.05 15 16 1 5.10 1.35 2 0.00 2.85 3 0.00 0.00 4 0.00 0.00 5 0.15 0.30 6 0.00 0.00 7 0.15 1.35 8 0.15 1.35 9 4.05 0.15 10 0.90 2.40 11 0.15 0.00 12 4.80 2.10 13 0.00 3.15 14 0.00 0.90 15 0.00 1.50 16 1.05 0.00 > social_blockmodel <- blockmodel(social_adj_mat, communities_full) > social_blockmodel Network Blockmodel: Block membership: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 3 3 2 2 1 1 3 1 2 2 1 5 Reduced form blockmodel: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Block 1 Block 2 Block 3 Block 4 Block 5 Block 1 4.2225 0.1200 0.2700 0.06 1.500 Block 2 0.1140 5.2875 0.0825 0.00 1.920 Block 3 0.2925 0.0750 4.5750 0.00 0.075 Block 4 0.0600 0.0000 0.0000 NaN 0.000 Block 5 1.0500 1.2000 0.3375 0.30 NaN > > # Because we retatined tie values above, we should compare the > # blockmodel values not to the graph's overall density but to its > # overall mean. > social_mean <- mean(social_adj_mat) > social_mean [1] 1.157227 > > # We can repeat one more time for the task-interaction network, > # once again retaining valued ties. > task_adj_mat <- get.adjacency(m182_task, attr='task_tie') > task_adj_mat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 0.00 0.00 0.00 0.00 0.30 0.00 0.00 0.00 0.30 0.30 0.0 0.15 0.00 0.00 0.15 2 0.00 0.00 0.00 0.00 0.00 0.00 0.75 0.30 0.00 0.00 0.0 0.00 0.90 0.15 0.15 3 0.00 0.00 0.00 0.00 0.15 0.60 0.00 0.00 0.00 0.00 0.3 0.00 0.00 0.00 0.00 4 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.15 0.0 0.00 0.00 0.00 0.00 5 0.30 0.00 0.15 0.00 0.00 0.75 0.00 0.00 0.00 0.00 2.1 0.00 0.15 0.00 0.00 6 0.00 0.00 0.75 0.00 0.45 0.00 0.00 0.00 0.00 0.15 0.3 0.00 0.00 0.00 0.00 7 0.00 1.20 0.00 0.00 0.00 0.00 0.00 0.15 0.00 0.00 0.0 0.00 0.30 0.00 0.00 8 0.00 0.45 0.00 0.00 0.00 0.00 0.30 0.00 0.00 0.00 0.0 0.00 0.75 0.15 0.00 9 0.15 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.30 0.0 2.70 0.00 0.00 0.15 10 0.15 0.00 0.00 0.15 0.00 0.30 0.00 0.00 0.45 0.00 0.0 0.75 0.00 0.00 0.30 11 0.00 0.00 0.15 0.00 1.80 0.45 0.00 0.00 0.00 0.00 0.0 0.00 0.00 0.00 0.00 12 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 2.40 0.45 0.0 0.00 0.00 0.00 0.75 13 0.00 1.05 0.00 0.00 0.00 0.00 0.30 0.60 0.00 0.00 0.0 0.00 0.00 0.00 0.00 14 0.00 0.30 0.00 0.00 0.15 0.15 0.15 0.30 0.00 0.00 0.0 0.00 0.00 0.00 0.00 15 0.15 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.15 0.30 0.0 0.45 0.00 0.00 0.00 16 4.65 4.80 0.75 1.05 2.40 1.20 2.40 1.95 2.85 5.40 1.2 5.25 3.90 3.90 5.55 16 1 5.10 2 4.80 3 0.30 4 0.90 5 1.80 6 0.90 7 2.85 8 2.40 9 2.40 10 5.40 11 1.05 12 4.50 13 4.50 14 3.15 15 6.60 16 0.00 > task_blockmodel <- blockmodel(task_adj_mat, communities_full) > task_blockmodel Network Blockmodel: Block membership: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 3 3 2 2 1 1 3 1 2 2 1 5 Reduced form blockmodel: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Block 1 Block 2 Block 3 Block 4 Block 5 Block 1 0.5250 0.0000 0.0300 0.03 4.8000 Block 2 0.0060 0.4050 0.0150 0.00 3.5400 Block 3 0.0225 0.0075 0.6625 0.00 1.0125 Block 4 0.0300 0.0000 0.0000 NaN 0.9000 Block 5 4.7400 3.3900 1.3875 1.05 NaN > > task_mean <- mean(task_adj_mat) > task_mean [1] 0.478125 > > # QUESTION #5 - Using the average density for each type of tie as > # an alpha-cutoff level, answer the following: (a) How do friendship > # cliques shape patterns of task and social interaction? (b) Are task > # or social interactions following clique boundaries? Why or why not > # might this happen? > > ### > # 5. K-CORES > ### > > # The graph.coreness() function in igraph returns a vector containing > # the degree of the highest-degree k-core to which each vertex > # belongs. > coreness = graph.coreness(m182_task) > coreness [1] 9 8 8 4 8 8 8 8 9 9 8 9 8 8 9 9 > > # Note that the output of graph.coreness refers simply to the *degree* > # of the k-core, not to the k-core itself; thus, two vertices both with > # coreness of 3 may not be connected at all and thus may be in separate > # k-cores. > # > # One way to get a sense of the actual k-core structure is to simply > # plot the graph and color-code by k-core: > make_k_core_plot <- function (g) { + lay1 <- layout.fruchterman.reingold(g) + plot(g, + vertex.color = graph.coreness(g), + layout=lay1, + edge.arrow.size = .5) + } > > make_k_core_plot(m182_friend) > make_k_core_plot(m182_social) > make_k_core_plot(m182_task) > > # Here's an artificial example showing two separate 3-cores: > g1 <- graph.ring(10) > g1 <- add.edges(g1, c(0,2, 1,3, 0,3, 5,7, 5,8, 6,8)) > make_k_core_plot(g1) > > # Question #6 - What's the difference between K-cores and cliques? > # Why might one want to use one over the other? > > > ### > # EXTRA CREDIT: > # igraph's built-in functionality merely shows the the degree of the > # highest-degree k-core to which each vertext belongs. However, > # vertices with the same coreness may be part of different k-cores, > # as shown in the artifical 3-core example above. > # > # Can you figure out a way to to generate not only the coreness of > # each vertex, but also an indicator of which specific k-core the > # vertex belongs to (and thus which other vertices are in the same > # k-core)? > ###