Reputation: 106
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
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
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)
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