Find individual brokerage triads from brokerage role analysis in R

73 Views Asked by At

I am using the brokerage (g, attribute) function from sna for R to find the Gould Fernandez brokerage roles of my network. I would like then to find the specific triads of this brokerage roles to analyse the alter-ego-alter relationships even further.

Does anyone have an idea which formula I can use to identify this specific triads?

Replicable Sample

g2 <- make_graph(~  A --+ B:D, B --+ D:F, C--+B , D--+A:B:F:E, E--+ D, F--+ A:E:G, G--+ F)
type<-c("one","two","three","one","two","three","one")
vertex_attr(g2,"type")<-type
g2_N<-intergraph::asNetwork(g2)

brokerage_roles<-brokerage(g2_N,type)
brokerage_roles$raw.nli

I receive the following brokerage role output

   w_I w_O b_IO b_OI b_O t
A   0   0    2    0   0 2
B   0   1    2    0   0 3
D   0   1    3    2   1 7
F   1   0    1    3   1 6
C   0   0    0    0   0 0
E   0   0    0    1   0 1
G   0   0    0    0   0 0

I would like to identify an approach to find out for example between which specific alters node A is brokering in the 2 b_01 triads found in the brokerage role node census and what type (node attribute) they have.

Within the sample network is easy to identify, but my actual data sets contains 125 nodes.

Thank you in advance for your help!

Potential Approach

I tried the potential approach described here to find all possible triads, classify them based on triad census terminology and then filter for the open triads to start to identify brokerage opportunties.

However the results seem not to be aligned with the brokerage role analysis and therefore the approach is erroneous.

node_triad_census(g2_N)

triads <- combn(1:network.size(g2_N),3, simplify = F) # all potential triad combinations

triad_census_test <- lapply(1:length(triads), 
                            function(x) triad.classify(g,tri=triads[[x]])) #create data frame with all possible triads

triads <- data.frame(matrix(unlist(triads), nrow=length(triads), byrow=T),
                     triad = unlist(triad_census_test)) #give classification to each triad
open_triads <- triads[which(triads$triad == "021D" |  # subset of triads 
                              triads$triad == "021U" | 
                              triads$triad == "021C" |
                              triads$triad == "111D" |
                              triads$triad == "111U" |
                              triads$triad == "201"),]

3

There are 3 best solutions below

1
tvg On

I don't know the answer but note that the brokerage function calls a C function called brokerage_R (see source code here). You might make some headway by inspecting this function to see what is happening under the hood. I inspected the output of this function by modifying the brokerage function to just output the raw result of the C code:

rawbrokerage <- function (g, cl) 
{
  g <- as.edgelist.sna(g)
  if (is.list(g)) 
    return(lapply(g, brokerage, cl))
  N <- attr(g, "n")
  m <- NROW(g)
  classes <- unique(cl)
  icl <- match(cl, classes)
  br <- matrix(0, N, 5)
  br <- .C("brokerage_R", as.double(g), as.integer(N), 
                  as.integer(m), as.integer(icl), brok = as.double(br), 
                  PACKAGE = "sna", NAOK = TRUE)
  
  return(br)
}

However I didn't find this very enlightening, which is why inspecting the C code could be helpful. I couldn't find the C code in the SNA source but it must be in there somewhere. The method is based on shortest paths, rather than a triad census, so even though it is limited to paths of length 2 I'm not sure that you could reproduce the result from a triad census.

0
AnCo On

I found the C code for the brokerage_R C code. Now I just have to understand it xD

void brokerage_R(double *g, int *pn, int *pm, int *cl, double *brok)
/*Calculate Gould-Fernandez brokerage scores for the vertices of g, based on
the vertex class vector cl.  Scores are recorded in a *pn x 5 matrix, brok,
whose columns are (in order) counts of coordinator, representative, 
gatekeeper, itinerant, and liason broker roles for each vertex.*/
{
  int n,i,j,k;
  slelement *ep,*ep2;
  snaNet *net;

  /*Set things up*/
  n=*pn;
  for(i=0;i<n;i++)
    for(j=0;j<5;j++)
      brok[i+n*j]=0.0;
  GetRNGstate();
  net=elMatTosnaNet(g,pn,pm);
  PutRNGstate();

  /*Calculate those scores!*/
  for(i=0;i<n;i++){                /*Walk the egos*/
    for(ep=snaFirstEdge(net,i,1);ep!=NULL;ep=ep->next[0])    /*ego->alter*/
      if(ep->val!=(double)i){
        for(ep2=snaFirstEdge(net,(int)(ep->val),1);ep2!=NULL;ep2=ep2->next[0])  /*alt->alt*/
          if((ep2->val!=(double)i)&&(ep2->val!=ep->val)){  /*Found 2-path?*/
            if(!snaIsAdjacent(i,(int)(ep2->val),net,0)){   /*Found broker?*/
              j=(int)(ep->val);
              k=(int)(ep2->val);
              /*Classify by type*/
              if(cl[j]==cl[i]){
                if(cl[j]==cl[k])
                  brok[j]++;         /*Type 0: Within-group (wI) [i j k]*/
                else
                  brok[j+2*n]++;     /*Type 2: Representative (bIO) [i j] [k]*/
              }else if(cl[j]==cl[k]){
                brok[j+3*n]++;       /*Type 3: Gatekeeping (bOI) [i] [j k]*/
              }else if(cl[i]==cl[k]){
                brok[j+n]++;         /*Type 2: Itinerant (WO) [j] [i k]*/
              }else
                brok[j+4*n]++;       /*Type 4: Liason (bO) [i] [j] [k]*/
            }
          }
      }
  }
}
1
tvg On

Maybe a simpler approach -- if you are mainly looking to explore the data or describe results, you could also just select nodes with high levels of particular brokerage roles and look at them visually. For example in your toy data node D has the highest total brokerage score. To see what is going on with this node you can just do:

ego.D <- make_ego_graph(g2, order =1, nodes = 3, mode = "all")[[1]]
plot(ego.D, vertex.color = factor(V(ego.D)$type))

You could easily loop over the nodes to look at more than one. Note that the make_ego_graph function seems to take node index numbers (3 in this case, because nodes are not sorted alphabetically) rather than names.