For a (two-mode) network N = ( (U,V), L ) described with matrix A the out-degree of node u ∈ U is equal to the sum of values in the row of u ; and the in-degree of node v ∈ V is equal to the sum of values in the column of v.
The same holds for temporal degrees.
def inDeg(A): return(MatVecLeft(MatBin(A),VecOne(len(A)))) def outDeg(A): return(MatVecRight(MatBin(A),VecOne(len(A[0]))))
Test
from TQmat import * import pickle with open("exampleA.p","rb") as p: V = pickle.load(p) print('keys = ',list(V.keys())) W = V['mat'] print("matrix"); MatList(W,all=False) print("Binary"); B = MatBin(W); MatList(B,all=False) print("outDegrees"); od = outDeg(W) for (i,d) in enumerate(od): print(i+1,d) print("inDegrees"); id = inDeg(W) for (i,d) in enumerate(id): print(i+1,d) # undirected degrees print("Binary/Edges") Ab = MatSetDiag(MatBin(W),N) print("matrix Ab"); MatList(Ab,all=False) S = MatSym(Ab) print("matrix S"); MatList(S,all=False) print("Degrees"); od = outDeg(S) for (i,d) in enumerate(od): print(i+1,d)
Results
keys = ['nam', 'mat', 'num', 'tit', 'tim'] matrix ( 1 , 2 ) = [(1, 8, 2), (9, 10, 4)] ( 2 , 3 ) = [(2, 7, 7), (8, 10, 3)] ( 2 , 6 ) = [(4, 6, 4), (8, 10, 5)] ( 3 , 2 ) = [(4, 9, 5)] ( 3 , 4 ) = [(1, 5, 5), (5, 9, 7)] ( 4 , 5 ) = [(1, 3, 4), (3, 10, 2)] ( 5 , 1 ) = [(3, 8, 1), (8, 9, 5)] ( 5 , 6 ) = [(1, 5, 6), (5, 7, 3), (9, 10, 5)] ( 6 , 3 ) = [(4, 8, 1), (8, 9, 5)] ( 6 , 4 ) = [(3, 7, 9), (8, 10, 8)] Binary ( 1 , 2 ) = [(1, 8, 1), (9, 10, 1)] ( 2 , 3 ) = [(2, 7, 1), (8, 10, 1)] ( 2 , 6 ) = [(4, 6, 1), (8, 10, 1)] ( 3 , 2 ) = [(4, 9, 1)] ( 3 , 4 ) = [(1, 9, 1)] ( 4 , 5 ) = [(1, 10, 1)] ( 5 , 1 ) = [(3, 9, 1)] ( 5 , 6 ) = [(1, 7, 1), (9, 10, 1)] ( 6 , 3 ) = [(4, 9, 1)] ( 6 , 4 ) = [(3, 7, 1), (8, 10, 1)] outDegrees 1 [(1, 8, 1), (9, 10, 1)] 2 [(2, 4, 1), (4, 6, 2), (6, 7, 1), (8, 10, 2)] 3 [(1, 4, 1), (4, 9, 2)] 4 [(1, 10, 1)] 5 [(1, 3, 1), (3, 7, 2), (7, 10, 1)] 6 [(3, 4, 1), (4, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 1)] inDegrees 1 [(3, 9, 1)] 2 [(1, 4, 1), (4, 8, 2), (8, 10, 1)] 3 [(2, 4, 1), (4, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 1)] 4 [(1, 3, 1), (3, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 1)] 5 [(1, 10, 1)] 6 [(1, 4, 1), (4, 6, 2), (6, 7, 1), (8, 9, 1), (9, 10, 2)] Binary/Edges matrix Ab ( 1 , 2 ) = [(1, 8, 1), (9, 10, 1)] ( 2 , 3 ) = [(2, 7, 1), (8, 10, 1)] ( 2 , 6 ) = [(4, 6, 1), (8, 10, 1)] ( 3 , 2 ) = [(4, 9, 1)] ( 3 , 4 ) = [(1, 9, 1)] ( 4 , 5 ) = [(1, 10, 1)] ( 5 , 1 ) = [(3, 9, 1)] ( 5 , 6 ) = [(1, 7, 1), (9, 10, 1)] ( 6 , 3 ) = [(4, 9, 1)] ( 6 , 4 ) = [(3, 7, 1), (8, 10, 1)] matrix S ( 1 , 2 ) = [(1, 8, 1), (9, 10, 1)] ( 1 , 5 ) = [(3, 9, 1)] ( 2 , 1 ) = [(1, 8, 1), (9, 10, 1)] ( 2 , 3 ) = [(2, 4, 1), (4, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 1)] ( 2 , 6 ) = [(4, 6, 1), (8, 10, 1)] ( 3 , 2 ) = [(2, 4, 1), (4, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 1)] ( 3 , 4 ) = [(1, 9, 1)] ( 3 , 6 ) = [(4, 9, 1)] ( 4 , 3 ) = [(1, 9, 1)] ( 4 , 5 ) = [(1, 10, 1)] ( 4 , 6 ) = [(3, 7, 1), (8, 10, 1)] ( 5 , 1 ) = [(3, 9, 1)] ( 5 , 4 ) = [(1, 10, 1)] ( 5 , 6 ) = [(1, 7, 1), (9, 10, 1)] ( 6 , 2 ) = [(4, 6, 1), (8, 10, 1)] ( 6 , 3 ) = [(4, 9, 1)] ( 6 , 4 ) = [(3, 7, 1), (8, 10, 1)] ( 6 , 5 ) = [(1, 7, 1), (9, 10, 1)] Degrees 1 [(1, 3, 1), (3, 8, 2), (8, 10, 1)] 2 [(1, 2, 1), (2, 4, 2), (4, 6, 3), (6, 9, 2), (9, 10, 3)] 3 [(1, 2, 1), (2, 4, 2), (4, 9, 3), (9, 10, 1)] 4 [(1, 3, 2), (3, 7, 3), (7, 8, 2), (8, 9, 3), (9, 10, 2)] 5 [(1, 3, 2), (3, 7, 3), (7, 10, 2)] 6 [(1, 3, 1), (3, 4, 2), (4, 6, 4), (6, 7, 3), (7, 8, 1), (8, 10, 3)]
We assume that the network N = (V,L) is simple one-mode network described with matrix A.
The clustering coefficient of node v ∈ V is equal to the ratio between the number of existing links between node's neighbors and the number of all possible links. For nodes of degree 0 and 1 we set clustering coefficient to 0.
In an undirected graph the number of all possible edges for node v is deg(v).(deg(v)-1)/2 ; and for directed graph the number of all possible arcs is deg(v).(deg(v)-1) .
We treat undirected graphs as directed in which each edge is replaced by a pair of opposite arcs.
It is easy to see that for simple undirected graphs the number of existing links between node's neighbors equals to the number of triangles with one vertex in node v. This number can be obtained as the diagonal value of the matrix A3 (removing the diagonals of A and A2 in computing).
For simple directed graphs without loops the procedure is more complicated - see Counting triangles.
print("Clustering coefficient") B = MatSetDiag(B,N); C = MatProd(B,B); MatList(C,all=False) print("square") D = MatSetDiag(C,N); MatList(D,all=False); tri = MatProdDiag(D,B) print("triangles") for (i,d) in enumerate(tri): print(i+1,d)
results
Clustering coefficient ( 1 , 1 ) = [(1, 3, 1), (3, 8, 2), (8, 10, 1)] ( 1 , 3 ) = [(2, 7, 1), (9, 10, 1)] ( 1 , 4 ) = [(3, 9, 1)] ( 1 , 6 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 2 , 2 ) = [(1, 2, 1), (2, 4, 2), (4, 6, 3), (6, 7, 2), (7, 8, 1), (8, 9, 2), (9, 10, 3)] ( 2 , 3 ) = [(4, 6, 1), (8, 9, 1)] ( 2 , 4 ) = [(2, 7, 1), (8, 9, 1)] ( 2 , 5 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 2 , 6 ) = [(4, 7, 1), (8, 9, 1)] ( 3 , 1 ) = [(2, 7, 1), (9, 10, 1)] ( 3 , 2 ) = [(4, 6, 1), (8, 9, 1)] ( 3 , 3 ) = [(1, 2, 1), (2, 4, 2), (4, 7, 3), (7, 8, 2), (8, 9, 3), (9, 10, 1)] ( 3 , 5 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 3 , 6 ) = [(4, 6, 1), (8, 10, 1)] ( 4 , 1 ) = [(3, 9, 1)] ( 4 , 2 ) = [(2, 7, 1), (8, 9, 1)] ( 4 , 4 ) = [(1, 9, 2), (9, 10, 1)] ( 4 , 6 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] ( 5 , 2 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 5 , 3 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 5 , 5 ) = [(1, 3, 2), (3, 7, 3), (7, 10, 2)] ( 6 , 1 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 6 , 2 ) = [(4, 7, 1), (8, 9, 1)] ( 6 , 3 ) = [(4, 6, 1), (8, 10, 1)] ( 6 , 4 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] ( 6 , 6 ) = [(1, 4, 1), (4, 6, 3), (6, 7, 2), (7, 8, 1), (8, 10, 2)] square ( 1 , 3 ) = [(2, 7, 1), (9, 10, 1)] ( 1 , 4 ) = [(3, 9, 1)] ( 1 , 6 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 2 , 3 ) = [(4, 6, 1), (8, 9, 1)] ( 2 , 4 ) = [(2, 7, 1), (8, 9, 1)] ( 2 , 5 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 2 , 6 ) = [(4, 7, 1), (8, 9, 1)] ( 3 , 1 ) = [(2, 7, 1), (9, 10, 1)] ( 3 , 2 ) = [(4, 6, 1), (8, 9, 1)] ( 3 , 5 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 3 , 6 ) = [(4, 6, 1), (8, 10, 1)] ( 4 , 1 ) = [(3, 9, 1)] ( 4 , 2 ) = [(2, 7, 1), (8, 9, 1)] ( 4 , 6 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] ( 5 , 2 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 5 , 3 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 6 , 1 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 6 , 2 ) = [(4, 7, 1), (8, 9, 1)] ( 6 , 3 ) = [(4, 6, 1), (8, 10, 1)] ( 6 , 4 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] triangles 1 [] 2 [(4, 6, 2), (8, 9, 2)] 3 [(4, 6, 2), (8, 9, 2)] 4 [] 5 [] 6 [(4, 6, 2), (8, 9, 2)] >>>
Clustering coefficients
def clusCoef(A,type=1): # type = 1 - standard clustering coefficient # type = 2 - corrected clustering coefficient / temporal degMax # type = 3 - corrected clustering coefficient / overall degMax nr = len(A); nc = len(A[0]) if nr!=nc: return(None) Ab = MatSetDiag(MatBin(A),N) S = MatSym(Ab) deg = MatVecRight(MatBin(S),VecOne(nr)) if type == 1: inv = [] for d in deg: e = [] for (s,f,v) in d: if v > 1: e.append((s,f,1/v/(v-1))) else: e.append((s,f,0)) inv.append(e) print("Invert") for (i,e) in enumerate(inv): print(i+1,e) tri = MatProdDiag(MatProd(S,Ab),S) cc = [] for (i,t) in zip(inv,tri): cc.append(TQprod(i,t)) return(cc) else: return(None)
# directed Clustering coefficient print("matrix SA") C = MatProd(S,Ab); MatList(C,all=False) tri = MatProdDiag(C,S) print("triangles") for (i,d) in enumerate(tri): print(i+1,d) cc = clusCoef(W) print("Clustering coefficient") for (i,c) in enumerate(cc): print(i+1,c) # undirected Clustering coefficient cc = clusCoef(S) print("Clustering coefficient") for (i,c) in enumerate(cc): print(i+1,c)
results
matrix SA ( 1 , 1 ) = [(1, 3, 1), (3, 8, 2), (8, 10, 1)] ( 1 , 3 ) = [(2, 4, 1), (4, 7, 2), (7, 8, 1), (9, 10, 1)] ( 1 , 4 ) = [(3, 9, 1)] ( 1 , 6 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 2 , 2 ) = [(1, 2, 1), (2, 4, 2), (4, 6, 6), (6, 7, 5), (7, 8, 2), (8, 9, 5), (9, 10, 3)] ( 2 , 3 ) = [(4, 6, 1), (8, 9, 1)] ( 2 , 4 ) = [(2, 4, 1), (4, 6, 3), (6, 7, 2), (7, 8, 1), (8, 9, 3), (9, 10, 1)] ( 2 , 5 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 2 , 6 ) = [(4, 7, 2), (7, 8, 1), (8, 9, 2)] ( 3 , 1 ) = [(2, 4, 1), (4, 7, 2), (7, 8, 1), (9, 10, 1)] ( 3 , 2 ) = [(4, 6, 1), (8, 9, 1)] ( 3 , 3 ) = [(1, 2, 1), (2, 4, 2), (4, 7, 6), (7, 8, 3), (8, 9, 6), (9, 10, 1)] ( 3 , 4 ) = [(4, 7, 1), (8, 9, 1)] ( 3 , 5 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 3 , 6 ) = [(3, 4, 1), (4, 6, 3), (6, 7, 1), (8, 9, 3), (9, 10, 1)] ( 4 , 1 ) = [(3, 9, 1)] ( 4 , 2 ) = [(2, 4, 1), (4, 6, 3), (6, 7, 2), (7, 8, 1), (8, 9, 3), (9, 10, 1)] ( 4 , 3 ) = [(4, 7, 1), (8, 9, 1)] ( 4 , 4 ) = [(1, 3, 2), (3, 7, 3), (7, 8, 2), (8, 9, 3), (9, 10, 2)] ( 4 , 5 ) = [(3, 7, 1), (9, 10, 1)] ( 4 , 6 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] ( 5 , 2 ) = [(3, 4, 1), (4, 6, 2), (6, 8, 1), (9, 10, 1)] ( 5 , 3 ) = [(1, 4, 1), (4, 7, 2), (7, 9, 1)] ( 5 , 4 ) = [(3, 7, 1), (9, 10, 1)] ( 5 , 5 ) = [(1, 3, 2), (3, 7, 3), (7, 10, 2)] ( 5 , 6 ) = [(3, 7, 1), (8, 10, 1)] ( 6 , 1 ) = [(3, 4, 1), (4, 6, 2), (6, 7, 1), (9, 10, 1)] ( 6 , 2 ) = [(4, 7, 2), (7, 8, 1), (8, 9, 2)] ( 6 , 3 ) = [(3, 4, 1), (4, 6, 3), (6, 7, 1), (8, 9, 3), (9, 10, 1)] ( 6 , 4 ) = [(1, 4, 1), (4, 7, 2), (7, 10, 1)] ( 6 , 5 ) = [(3, 7, 1), (8, 10, 1)] ( 6 , 6 ) = [(1, 3, 1), (3, 4, 2), (4, 6, 4), (6, 7, 3), (7, 8, 1), (8, 10, 3)] triangles 1 [] 2 [(4, 6, 4), (8, 9, 4)] 3 [(4, 6, 6), (6, 7, 2), (8, 9, 6)] 4 [(3, 4, 2), (4, 7, 4), (8, 10, 2)] 5 [(3, 7, 2), (9, 10, 2)] 6 [(3, 4, 2), (4, 6, 8), (6, 7, 4), (8, 9, 6), (9, 10, 2)] Invert 1 [(3, 8, 0.5), (8, 10, 0)] 2 [(2, 4, 0.5), (4, 6, 0.0833), (6, 7, 0.1667), (7, 8, 0.5), (8, 10, 0.1667), (8, 10, 0)] 3 [(2, 4, 0.5), (4, 7, 0.0833), (7, 8, 0.1667), (8, 9, 0.0833), (9, 10, 0)] 4 [(1, 3, 0.5), (3, 7, 0.1667), (7, 8, 0.5), (8, 9, 0.1667), (9, 10, 0.5), (9, 10, 0)] 5 [(1, 3, 0.5), (3, 7, 0.1667), (7, 10, 0.5), (7, 10, 0)] 6 [(3, 4, 0.5), (4, 6, 0.0833), (6, 7, 0.1667), (8, 10, 0.1667), (8, 10, 0)] Clustering coefficient 1 [] 2 [(4, 6, 0.0833), (8, 9, 0.1667)] 3 [(4, 6, 0.3333), (6, 7, 0.0833), (8, 9, 0.3333)] 4 [(3, 4, 0.1667), (4, 7, 0.5), (8, 9, 0.3333), (9, 10, 0.5)] 5 [(3, 7, 0.1667), (9, 10, 0.5)] 6 [(3, 4, 0.5), (4, 6, 0.25), (6, 7, 0.1667), (8, 9, 0.3333), (9, 10, 0.1667)] Invert 1 [(1, 3, 0.5), (3, 8, 0.0833), (8, 10, 0.5), (8, 10, 0)] 2 [(1, 2, 0.5), (2, 4, 0.0833), (4, 6, 0.0333), (6, 9, 0.0833), (9, 10, 0.0333), (9, 10, 0)] 3 [(1, 2, 0.5), (2, 4, 0.0833), (4, 9, 0.0333), (9, 10, 0.5), (9, 10, 0)] 4 [(1, 3, 0.0833), (3, 7, 0.0333), (7, 8, 0.0833), (8, 9, 0.0333), (9, 10, 0.0833), (9, 10, 0)] 5 [(1, 3, 0.0833), (3, 7, 0.0333), (7, 10, 0.0833), (7, 10, 0)] 6 [(1, 3, 0.5), (3, 4, 0.0833), (4, 6, 0.0179), (6, 7, 0.0333), (7, 8, 0.5), (8, 10, 0.0333), (8, 10, 0)] Clustering coefficient 1 [] 2 [(4, 6, 0.2667), (8, 9, 0.6667)] 3 [(4, 6, 0.5333), (6, 7, 0.2666), (8, 9, 0.5333)] 4 [(3, 4, 0.2667), (4, 7, 0.5333), (8, 9, 0.2667), (9, 10, 0.6667)] 5 [(3, 7, 0.2667), (9, 10, 0.6667)] 6 [(3, 4, 0.6667), (4, 6, 0.4286), (6, 7, 0.5333), (8, 9, 0.5333), (9, 10, 0.2667)] >>>
May be we need to add the parameter directed/undirected.