Gary DeYoung
Gary DeYoung

Reputation: 106

Calculating ratio of reciprocated ties for each node in igraph

I am calculating the ratio of reciprocated friendships for students in a classroom. I have created the network, called SA1Pref.net, and identified the number of reciprocated ties for each student, using the following code:

recip<-is.mutual(SA1Pref.net)
recip<-as.data.frame(recip)

This gives me the following data frame:

head(recip)

  recip
1 FALSE
2  TRUE
3 FALSE
4  TRUE
5  TRUE
6  TRUE

So far so good. Then I create an edge list from my network, and merge that with the list of reciprocated ties. So now I can tell which nodes are reciprocated and which aren't:

edgelist<-as_data_frame(SA1Pref.net, what = "edges")
dyad<- cbind(edgelist, recip)

head(dyad)
          from       to weight recip
    1 S109.0.6 S105.0.5      2 FALSE
    2 S109.0.6 S103.0.2      2  TRUE
    3 S109.0.6 S110.0.8      1 FALSE
    4 S109.0.6 S115.0.3      1  TRUE
    5 S105.0.5 S103.0.2      1  TRUE   
    6 S105.0.5 S110.0.8      1  TRUE

"Weight" irrelevant to my question, so feel free to ignore that.

What I want to do is calculate the number of reciprocated tie for each node. So S109.0.6 would be two. Once I have that, I want to divide the reciprocated ties by the outdegree for each node. I've also created a data frame for the outdegree, which looks like this:

head(outdegree)

              outdegree
    S109.0.6         4
    S105.0.5         3
    S103.0.2         3
    S110.0.8         4
    S115.0.3         6
    S108.1.6         4

So, the ratio for S109.0.6 would be .5.

I could do this all by hand, but I have 48 of these networks to run, and I want it to be efficient and to prevent mistakes.

Is there an easy way to do this? It seems like something R should be able to do without a problem, but I'm having a terrible time finding a solution.

Thank you for your help.

Note: Fairly new to R, social network analysis, and stackoverflow. Your help is appreciated.

Adding example dataset and solution in response to comments

###Edgelist of reciprocated nodes###

From<- c("A", "A", "A", "B", "B", "B", "C", "D", "D")

To<- c("B", "C", "D", "A", "C", "D", "A", "B", "C")

Recip<- c(TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, 
TRUE, FALSE)


fakenet<- data.frame(From, To, Recip)


> fakenet
  From To Recip
1    A  B  TRUE
2    A  C  TRUE
3    A  D FALSE
4    B  A  TRUE
5    B  C FALSE
6    B  D  TRUE
7    C  A  TRUE
8    D  B  TRUE
9    D  C FALSE


###Outdegree###

Student<- c("A","B","C","D")

Outdegree<- c(3, 3, 1, 2)

df.Outdegree<- data.frame(Student, Outdegree)

> df.Outdegree
  Student Outdegree
1       A         3
2       B         3
3       C         1
4       D         2

A's ratio would be .67, because it has an outdegree of 3 and two reciprocated ties. B's ratio would also be .67, C's would be 1, and D's would be .5. So the ratio would be reciprocated ties/outdegree.

Upvotes: 2

Views: 402

Answers (1)

gos
gos

Reputation: 484

This should do what you want.

outdegree$ratio <- aggregate(recip~from,dyad,sum)$recip/outdegree$outdegree
outdegree

##         outdegree     ratio
##S109.0.6         4 0.5000000
##S109.0.5         3 0.6666667

Explanation

aggregate groups the data in dyad together based on the rowname and applies the sum function the recip column of each group. In R, when you perform sum on a logical (boolean) vector, it will add all the TRUE values. I'm not sure what you're using this for, but you may also find the mean function useful, which would return the ratio of TRUE values to the total.

The rest of the line divides by the respective outdegree for that row.

If you want to round them, as your example suggests, you can use outdegree$ratio <- round(outdegree$ratio,2)

Example

Using your provided extra dataset:

outdegree$ratio <- aggregate(recip~from,dyad,sum)$recip/outdegree$outdegree
outdegree$ratio <- round(outdegree$ratio,2)
outdegree

##  outdegree ratio
##A         3  0.67
##B         3  0.67
##C         1  1.00
##D         2  0.50

Upvotes: 1

Related Questions