10. Raw dyadic interaction data

Feb 9, 2013: These codes have been updated for igraph v0.6 in R 2.15.

This page is somewhat related to the 'edgelists with associated edge values' page:
Here, I will address how we go from the type of data I often deal with--a list of outcomes of interactions, whereby the same combination of individuals might interact multiple times over time. The data format look like something like a typical edgelist, except that each row represents a single interaction instead of a dyadic relation (which is the sum total of all observed interactions).
So the question is, how can we efficiently convert data on a set of interactions to a network of relations.

For example:

Winner Loser
23871 23778
23871 58098
23778 23824
23732 58098
23871 23778
23778 23732
23871 23778
23871 58009
23732 58098
58009 58098
23778 23732
23871 58098
23732 58098
23871 23778
23732 58098
23732 58098
.
.
.

.
.
.


The full data is available below as 'interactions.csv'. This is actually an alternate format of the 'weighted edgelist' from the previous page.
For simplicity, this dataset does not contain any 'reversals'... but we'll deal with data with reversals a bit later.

This type of data can be converted easily to a network. Here's an example in igraph:


library(igraph)
el=as.matrix(read.csv(file.choose()))
el[,1]=as.character(el[,1])#Because the vertex IDs in this dataset are numbers, we make sure igraph knows these should be treated as characters. Otherwise, it'll create problems.
el[,2]=as.character(el[,2])
g=graph.edgelist(el)

a=get.adjacency(g,sparse=FALSE)
a


23871 23778 58098 23824 23732 58009 58256
23871 0 15 5 0 0 1 0
23778 0 0 0 1 8 0 0
58098 0 1 0 0 0 0 0
23824 0 0 0 0 0 0 0
23732 1 0 10 0 0 0 0
58009 0 0 7 0 0 0 0
58256 0 0 1 0 0 0 0

This should be the same as the same adjacency matrix we get in the 'edgelist with edge values' page, although the order of the vertices are different.

**HOWEVER, there is one problem with this network. Even though the adjacency matrix suggests that the edge weight information is included in this igraph object, there in fact is no edge weight here. This is clear if we just look at the summary information for g.

summary(g)

> summary(g)
IGRAPH DN-- 7 50 -- 
attr: name (v/c)

This network does not have edge weights.

So, to make a network that actually incorporates edge weights, we have to go from the adjacency matrix (which, as shown above, has the weight values) and make a new igraph object:

a=get.adjacency(g)
g.weight=graph.adjacency(a,mode="directed",weighted=TRUE)
summary(g.weight)

IGRAPH DNW- 7 10 -- 
attr: name (v/c), weight (e/n)

Ok, so now we have what we want--a network that summarizes the cumulative interactions of all dyads.
So if we plot this figure:
plot(g.weight,edge.width=E(g.weight)$weight/2)

This is identical to the previous page.



## Reversals

Ok, now let's deal with reversals.
First, we'll switch up the dataset a little bit to create some reversals. We'll just flip the winners & losers of 10 out of the 50 interactions.

n=sample(nrow(el),10) #randomly sample 10 numbers between 1 through [number of rows in el] (in this case, 50).
el2=el
el2[n,]=el[n,c(2:1)] #for those randomly selected 10 rows, swap columns 1 & 2

g.alt=graph.edgelist(el2) #create a network from this altered interaction list
a.alt=get.adjacency(g.alt,sparse=FALSE) #the adjacency matrix of this alternate network
a.alt



23871 23778 58098 23824 23732 58009 58256
23871 0 11 5 0 0 1 0
23778 4 0 0 1 6 0 0
58098 0 1 0 0 2 2 0
23824 0 0 0 0 0 0 0
23732 1 2 8 0 0 0 0
58009 0 0 5 0 0 0 0
58256 0 0 1 0 0 0 0

Here, we see that, for example, #23871 beat #23778 11 times, but #23778 beat #23871 4 times.

Now, here is the crux of the problem--given that two individuals trade-off winning & losing, what is the relation between these two individuals? The simplest way is to say 'the individual that wins a majority of interaction is dominant'. This is clearly very simplistic, but it's probably the easiest and the possible alternatives are likely just as arbitrary...
... so, let's just go with 'majority wins'. Then, we need to convert this matrix of interactions into a matrix that actually represents dominance relations, based on cumulative interactions.

Here's one way to do that:
interactions=a.alt+t(a.alt) #the number of interactions between dyads is the sum of the current matrix and the transpose of the matrix

m=a.alt/interactions #we then divide the number of wins by the corresponding number of interactions
m[m>0.5]=1 #if you win >50% of interactions with this guy, you get a 1
m[m<0.5]=0 #if you win <50% of interactions with this guy, you get a 0
m[is.na(m)]=0 #NaNs mean there were no interactions for this dyad, so they both get 0s
m[m==0.5]=0    #If they win equal number of interactions, the dyad is tied... what you do with these kind of depends on your question. You can either set it to 0 because the relation is 'unresolved', or you can set is to 0.5 because they 'split the difference', or you can set both to 1 because they are 'mutual winners'. Here, ties = 0. 
m


23871 23778 58098 23824 23732 58009 58256
23871 0 1 1 0 0 1 0
23778 0 0 0 1 1 0 0
58098 0 1 0 0 0 0 0
23824 0 0 0 0 0 0 0
23732 1 0 1 0 0 0 0
58009 0 0 1 0 0 0 0
58256 0 0 1 0 0 0 0

...as I wrote on the code annotations, you have to set up a guideline for yourself about what to do with 'non-interactions' and 'ties'. The other obvious flaw is that we lose all information about the proportion of times an individual won, etc... but these issues are beyond the scope of this little page.



ċ
interactions.csv
(1k)
Dai Shizuka,
Feb 24, 2012, 12:55 PM
Comments