2

I need to determine the transitivity for each node in a network, but am getting inconsistent results.

set.seed(123)    
a <- rbinom(144, 1, .5)
b <- graph.adjacency(matrix(a, nrow = 12, ncol = 12), mode = "undirected")

transitivity(b, type = "local")

This provides the output:

 [1] 0.6888889 0.4909091 0.4444444 0.9333333 0.4909091 0.7500000 0.7333333 0.4666667 0.7333333 0.4222222 0.5000000
[12] 0.6944444

But when I try to specify a single node, some values in the output do not match:

transitivity(b, vids = 2, type = "local")

[1] 0.75

In fact, when I try to calculate the local transitivity for all vertices, many are different than if I leave the vids argument out. In some instances when I've tried this, all have been different.

transitivity(b, vids = V(b), type = "local")

  [1] 0.6888889 0.7500000 0.7142857 0.9333333 0.7500000 0.7500000 0.7333333 0.7500000 0.7333333 0.6785714 0.8571429
[12] 0.6944444

If I set vids as NULL it matches the first output, without the vids argument included at all.

The results are slightly different, but still don't match if I create a directed network.

Any thoughts on what might be causing this or which set of results should I use?

Thank you for your help.

Szabolcs
  • 24,728
  • 9
  • 85
  • 174
Gary DeYoung
  • 106
  • 7

2 Answers2

2

You should be aware of that your graph b is NOT a simple graph, since it contains self loops

enter image description here

When running transitivity over such kind of graph, you will see a warning/error message

Transitivity works on simple graphs only. The result might be incorrect. igraph 1.3.0 and later will treat this as an error.

Thus, if you would like to use transitivity in a correct manner, you should exclude self loops first, e.g.,

b <- simplify(graph.adjacency(matrix(a, nrow = 12, ncol = 12), mode = "undirected"))

and then you will see

> transitivity(b, type = "local")
 [1] 0.6888889 0.7500000 0.7142857 0.9333333 0.7500000 0.7500000 0.7333333
 [8] 0.7500000 0.7333333 0.6785714 0.8571429 0.6944444

> transitivity(b, vids = V(b), type = "local")
 [1] 0.6888889 0.7500000 0.7142857 0.9333333 0.7500000 0.7500000 0.7333333
 [8] 0.7500000 0.7333333 0.6785714 0.8571429 0.6944444
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
  • Thanks for the response, and for catching the self-loops. I inadvertently included them in my minimal reproducible example, but they don't exist in the graph I'm working on. I can revise the question if it's helpful. Do you know of anything else that might be causing the different results? Using the simplify function isn't helping with the graph I'm working on. – Gary DeYoung Jan 25 '22 at 22:17
  • Check that. I set my actual graph to undirected (it's directed) and simplified and it worked. Appreciate the help. – Gary DeYoung Jan 25 '22 at 22:21
  • 1
    @GaryDeYoung A simple directed graph with reciprocal edges is effectively non-simple when ignoring edge directions. – Szabolcs Jan 26 '22 at 07:51
2

As Thomas said, the result you get from transitivity(b, type = "local") is incorrect because b is not simple, and local transitivity calculations are not supported for non-simple graphs in R/igraph 1.2.x. If you use the latest version, there will be a clear warning:

> transitivity(b, type = "local")
Transitivity works on simple graphs only. The result might be incorrect. igraph 1.3.0 and later will treat this as an error.
 [1] 0.6888889 0.4909091 0.4444444 0.9333333 0.4909091 0.7500000 0.7333333 0.4666667
 [9] 0.7333333 0.4222222 0.5000000 0.6944444

If you don't see this warning, then please updgrade to igraph 1.2.11.

How come that transitivity(b, type='local") and transitivity(b, vids=V(b), type='local") give different results? This is because internally different code paths are used when calculating the result for all vertices vs a specific subset of vertices, in an attempt to improve performance.

The warning message says that "igraph 1.3.0 and later will treat this as an error." but in fact a tremendous amount of improvements have gone into version 1.3 since then and support for multigraphs has already been added (more precisely, this has been added to C/igraph 0.9, which R/igraph 1.3 will be based on).

I encourage you to try the development version of R/igraph, which will become version 1.3.0. Installation instructions are here; note that you need to have the R development tools installed (on Windows/Mac), as the package compiles from source. This version has a large number of fixes compared to the 1.2.x series, and at this point, should be considered more reliable than the "stable" 1.2.11.

Szabolcs
  • 24,728
  • 9
  • 85
  • 174
  • Thanks so much for the explanation. I'll give the development version a shot--that might really help me along with my project. – Gary DeYoung Jan 26 '22 at 16:53
  • @GaryDeYoung Please post any feedback to https://igraph.discourse.group/ (or if you found an obvious bug, then https://github.com/igraph/rigraph/issues/new/choose) – Szabolcs Jan 26 '22 at 16:58
  • Might not be the best forum for this, but I'm getting an error. These seem to be the relevant lines: gfortran -mmacosx-version-min=10.13 -fno-optimize-sibling-calls -fPIC -Wall -g -O2 -c vendor/arpack/dgetv0.f -o vendor/arpack/dgetv0.o make: gfortran: No such file or directory make: *** [vendor/arpack/dgetv0.o] Error 1 ERROR: compilation failed for package ‘igraph’ * removing ‘/private/var/folders/_2/kx476bwd1pd09h3hwky7fhnw0000gn/T/RtmpTnQ7CQ/Rinste4b4521c22ff/igraph’ I did install fortran as linked on the CRAN site. I also updated to the most recent version of R. Any thoughts? – Gary DeYoung Jan 26 '22 at 20:56
  • @GaryDeYoung Please ask about this on the forum (link above), and provide some information about your systems (which R, which gfortran, any custom Makevars, etc.) – Szabolcs Jan 27 '22 at 09:20