These functions offer methods for summarising the closure in configurations in one- and two-mode networks:

  • node_by_reciprocity() measures nodes' reciprocity.

  • node_by_transitivity() measures nodes' transitivity.

  • node_by_equivalency() measures nodes' equivalence or reinforcement in a (usually two-mode) network.

node_by_reciprocity(.data)

node_by_transitivity(.data, variant = c("watts", "barrat", "onnela", "zhang"))

node_by_equivalency(.data)

Arguments

.data

A network object of class stocnet, igraph, tbl_graph, network, or similar. Internally any of these will be coerced to an efficient implementation. For more information on possible coercions, see e.g. manynet::as_stocnet().

variant

Character string naming which variant of the measure to compute, where more than one definition of the same quantity is in use. The variant chosen is reported when the result is printed.

Value

A node_measure numeric vector the length of the nodes in the network, providing the scores for each node. If the network is labelled, then the scores will be labelled with the nodes' names.

The object also carries the measure it computed, the range its values can fall within, and whether and how those values were normalized. These are shown as a one-line header when the object is printed. Where a measure offers a choice between several ways of counting the same thing, it also carries the variant it used. All can be retrieved with attr().

Details

For one-mode networks, node_by_reciprocity is a shallow wrapper of the igraph version, and node_by_transitivity offers the igraph version alongside three weighted clustering coefficients.

For two-mode networks, node_by_equivalency calculates the proportion of three-paths in the network that are closed by fourth tie to establish a "shared four-cycle" structure.

Cognitive social structures

A cognitive social structure records each node's report of the ties in the whole network, in a by column that names who reported each tie. Counting every report as a tie of its own would count each tie once for every perceiver who reports it. So the functions here first combine the reports into the locally aggregated structure of Krackhardt (1987), with the intersection rule: a tie exists if both of its ends report it, and a message says so. A tie that names no reporter is kept as it is.

A tie-level function still returns one value for each report, so that the result can be added back to the network it was given. Each report takes the value of the tie that it reports. A report of a tie that is not in the aggregated structure takes NA, or FALSE for a mark. tie_is_random() is the exception, and draws among the reports.

To combine the reports in a different way, do this before the function, e.g. with manynet::to_aggregated(over = "by").

Krackhardt, David. 1987. "Cognitive social structures". Social Networks 9(2): 109-134. doi:10.1016/0378-8733(87)90009-8

Node reciprocity

A node's reciprocity is the proportion of its ties that are returned. Where a network is undirected, including where it is two-mode, there is no direction for a tie to be returned along, so every node scores 1. This is what net_by_reciprocity() reports for such a network too.

Node transitivity

A node's transitivity is the proportion of its neighbours that are themselves connected, which is also known as the local clustering coefficient of the node. Where \(a_{ij}\) indicates a tie and \(k_i\) is the node's degree, the "watts" variant (Watts and Strogatz 1998) counts the node's closed triangles: $$C_i = \frac{\sum_{j,h} a_{ij} a_{ih} a_{jh}}{k_i(k_i - 1)}$$

The other variants weight each triangle by the ties' weights \(w_{ij}\), and differ in which weights count:

  • "barrat" (Barrat et al. 2004) weights each triangle by the mean weight of the node's own two ties in it, divided by the node's strength \(s_i\). Only whether the tie opposite the node is present counts: $$C_i = \frac{1}{s_i(k_i - 1)} \sum_{j,h} \frac{w_{ij} + w_{ih}}{2} a_{ij} a_{ih} a_{jh}$$

  • "onnela" (Onnela et al. 2005) weights each triangle by the geometric mean of all three of its weights, each divided by the network's largest weight, so that a triangle closed by a weak tie counts for less: $$C_i = \frac{1}{k_i(k_i - 1)} \sum_{j,h} (\hat{w}_{ij} \hat{w}_{ih} \hat{w}_{jh})^{1/3}$$

  • "zhang" (Zhang and Horvath 2005) divides the product of the three weights by the most that the node's own weights allow: $$C_i = \frac{\sum_{j,h} \hat{w}_{ij} \hat{w}_{ih} \hat{w}_{jh}}{(\sum_j \hat{w}_{ij})^2 - \sum_j \hat{w}_{ij}^2}$$

Saramäki et al. (2007) compare the three. On an unweighted network, all four variants give the same values. The first choice, "watts", is the default on an unweighted network only. On a weighted network, the default is "barrat", since this is the weighted form that reduces most directly to the unweighted one; use variant = "watts" to ignore the weights. A node with fewer than two ties has no pair of neighbours to close, and scores NaN in every variant. A two-mode network contains no triangles, so every node scores 0 or NaN.

Directed networks

Transitivity here ignores the direction of ties. The weighted variants add the weights of the two directions of a tie, following Fagiolo (2007). Every weighted variant is unchanged when all weights are multiplied by the same number, so this gives the same result as their mean. To combine the two directions differently, use manynet::to_undirected() first.

Multiplex networks

The "watts" variant counts a pair of nodes as tied if they are tied in any layer. The weighted variants add the weights of the parallel ties between two nodes, so that, in an unweighted multiplex network, a tie is weighted by the number of layers it appears in. To measure one layer alone, use manynet::to_uniplex() first.

Signed networks

A tie counts here however it is signed, so each tie is read by the magnitude of its weight. To consider only the positive ties, use manynet::to_unsigned(keep = "positive") first.

References

On the local clustering coefficient

Watts, Duncan J., and Steven H. Strogatz. 1998. "Collective dynamics of 'small-world' networks". Nature 393(6684): 440-442. doi:10.1038/30918

Holland, Paul W., and Samuel Leinhardt. 1971. "Transitivity in structural models of small groups". Comparative Group Studies 2(2): 107-124. doi:10.1177/104649647100200201

On weighted clustering

Barrat, Alain, Marc Barthelemy, Romualdo Pastor-Satorras, and Alessandro Vespignani. 2004. "The architecture of complex weighted networks". Proceedings of the National Academy of Sciences 101(11): 3747-3752. doi:10.1073/pnas.0400087101

Onnela, Jukka-Pekka, Jari Saramäki, János Kertész, and Kimmo Kaski. 2005. "Intensity and coherence of motifs in weighted complex networks". Physical Review E 71(6): 065103. doi:10.1103/PhysRevE.71.065103

Zhang, Bin, and Steve Horvath. 2005. "A general framework for weighted gene co-expression network analysis". Statistical Applications in Genetics and Molecular Biology 4(1): 17. doi:10.2202/1544-6115.1128

Saramäki, Jari, Mikko Kivelä, Jukka-Pekka Onnela, Kimmo Kaski, and János Kertész. 2007. "Generalizations of the clustering coefficient to weighted complex networks". Physical Review E 75(2): 027105. doi:10.1103/PhysRevE.75.027105

Fagiolo, Giorgio. 2007. "Clustering in complex directed networks". Physical Review E 76(2): 026107. doi:10.1103/PhysRevE.76.026107

Examples

node_by_reciprocity(ison_networkers)
#> # Reciprocity, normalized [0, 1]
#> ▁▁▁▁▁▂▃▃ 
#>   `Lin Freeman` `Doug White` `Ev Rogers` `Richard Alba` `Phipps Arabie`
#> 1         0.935         0.75           1          0.944           0.286
#> # ... and 27 more values from this nodeset. Use `print_all(...)` to print all values.
node_by_transitivity(ison_adolescents)
#> # Transitivity, normalized [0, 1]
#> ▂▃▂▂▂ 
#>   Betty   Sue Alice  Jane  Dale   Pam Carol  Tina
#> 1   NaN 0.333   0.5     1 0.667 0.333     0   NaN
node_by_transitivity(ison_networkers)
#> # Barrat transitivity, normalized [0, 1]
#> ▁▂▁▂▂▃ 
#>   `Lin Freeman` `Doug White` `Ev Rogers` `Richard Alba` `Phipps Arabie`
#> 1         0.708        0.789       0.926          0.859           0.751
#> # ... and 27 more values from this nodeset. Use `print_all(...)` to print all values.
node_by_transitivity(ison_networkers, variant = "onnela")
#> # Onnela transitivity, normalized [0, 1]
#> ▁▁▃▃▂▁▁ 
#>   `Lin Freeman` `Doug White` `Ev Rogers` `Richard Alba` `Phipps Arabie`
#> 1         0.054         0.03       0.017          0.032           0.009
#> # ... and 27 more values from this nodeset. Use `print_all(...)` to print all values.