These functions construct a square, node-by-node matrix of how alike the nodes of a one-mode network are:

  • to_proximity() compares each pair of nodes on their ties, using any of the measures that to_mode1() offers.

  • to_correlation() performs a Pearson pairwise correlation, choosing how to treat the diagonal and the reciprocal ties from the network's format.

  • to_cosine() takes the cosine of the angle between the columns of a matrix.

Where to_mode1() compares nodes on their affiliations to a second mode, these functions compare nodes on their ties to one another. The two share one measure vocabulary and differ only in the profile compared.

to_proximity(
  .data,
  similarity = .proj_measures,
  across = c("rows", "columns", "both"),
  dyad = NULL
)

to_correlation(.data, method = NULL)

to_cosine(.data)

Arguments

.data

An object of a {manynet}-consistent class:

  • adjacency or incidence matrix from {base} R

  • edgelist data.frame from {base} R or tbl/tbl_df from {tibble}

  • stocnet stocnet, from the {manynet} package

  • igraph igraph, from the {igraph} package

  • network network, from the {network} package

  • tidygraph tbl_graph, from the {tidygraph} package

similarity

Method for establishing ties in the projection, "count" by default.

The measures are grouped below by what they are sensitive to. Within a group they are monotone transformations of one another, and so rank dyads identically, differing only in their scale. Choosing between the groups therefore matters rather more than choosing within one.

Measures defined for valued as well as binary data:

  • "count" counts the coinciding ties, the cross-product \(XX'\). For valued data it sums the products of tie strengths. Interpret it as the degree of opportunity between two nodes. This is the default, and the quickest, since it can use igraph::bipartite_projection() directly.

  • "match" counts the cells in which two nodes hold exactly the same value, joint absences included. For binary data this is "rand" multiplied by the number of nodes in the other mode, but for valued data it is the more general measure, since it registers agreement at any tie strength. Use it where the level of involvement is meaningful in itself.

  • "overlap" divides the count by the smaller of the two nodes' total tie strength, the Szymkiewicz-Simpson coefficient. Use it where one node is much more active than the other, and the less active node's rarity should not depress the score.

  • "crossmin" sums the smaller of each pair of tie strengths. Interpret it as the capacity two nodes could jointly bring to bear. For binary data it reduces to "count".

  • "maxcrossmin" takes the largest such minimum rather than their sum, so that a single strong shared affiliation stands for the pair. For binary data it collapses to an indicator of any shared affiliation, and so is of little use there.

  • "sqdiff" inverts the sum of squared differences in tie strength, as \(1/(1+d)\), so that identical rows give 1 and larger values mean more alike, as for every other measure here. Recover the raw sum of squared differences as \(1/x - 1\).

  • "pearson" gives Pearson's product-moment correlation and "covariance" its unstandardised counterpart. Use "covariance" where the variance in involvement is itself of interest, and "pearson" where it is not.

  • "spearman" and "kendall" are the rank counterparts of "pearson". Use them where tie strengths order the affiliations reliably but their spacing does not, as with ordinal ratings.

  • "cosine" gives the cosine of the angle between two nodes' rows. It differs from "pearson" in not centring them first, so that it reads two nodes as alike where their involvements are proportional rather than where they depart from the average in the same direction. For binary data it agrees with "ochiai", except that a node with no ties at all is reported as no more similar to another than any other node, where "ochiai" would divide by zero.

  • "euclidean" and "manhattan" invert the straight-line and the city-block distance between two rows, again as \(1/(1+d)\). "manhattan" sums the absolute differences in tie strength, so that a large discrepancy on one affiliation counts no more than the same total spread over several; "euclidean" penalises the concentrated discrepancy more heavily, as "sqdiff" does. Recover either raw distance as \(1/x - 1\).

Measures defined for binary data only, where a valued network is dichotomised at zero with a warning. Writing \(a\) for the cells in which both nodes are present, \(b\) and \(c\) for those in which just one is, and \(d\) for those in which neither is:

  • Sensitive to co-presence, ignoring joint absence: "jaccard" is \(a/(a+b+c)\), opportunity weighted by participation; "czekanowski" (the Dice or Sorensen coefficient) is \(2a/(2a+b+c)\), which double-weights co-presence; and "sokalsneath" is \(a/(a+2(b+c))\), which instead double-weights mismatch. Use these where joint non-participation says nothing, as in a sparse affiliation network with many events.

  • Sensitive to matching, counting joint absence as evidence: "rand", the Simple Matching Coefficient, is \((a+d)/(a+b+c+d)\); "hamann" is \(((a+d)-(b+c))/(a+b+c+d)\), the same quantity rescaled onto \([-1,1]\) so that its sign reports whether matches outnumber mismatches; and "rogerstanimoto" is \((a+d)/(a+2(b+c)+d)\), which double-weights mismatch. Interpret these as the degree of behavioural mirroring between two nodes, and use them where not attending is as informative as attending.

  • Sensitive to association, through the odds ratio \(ad/bc\): "yule" is Yule's Q, \((ad-bc)/(ad+bc)\), which has a straightforward reading as a rescaled odds ratio; and "bonacich" is \(\sqrt{ad}/(\sqrt{ad}+\sqrt{bc})\), which is Yule's Y rescaled onto \([0,1]\). Both saturate at 1 wherever \(b\) or \(c\) is zero.

  • Geometric: "ochiai" is \(a/\sqrt{(a+b)(a+c)}\), the cosine of the angle between two nodes' affiliation vectors, and "ochiai2" (also known as Sokal and Sneath's fifth measure) is \(ad/\sqrt{(a+b)(a+c)(d+b)(d+c)}\), its counterpart including joint absence. Neither is monotone in any of the above, so both are worth trying alongside them.

  • "hamming" inverts the Hamming distance, the number of cells in which the two nodes differ, as \(1/(1+d)\). It is a monotone transformation of "rand", and so ranks dyads identically, but states the disagreement as a count rather than as a proportion of agreement.

across

Which margin of the network the operation is taken over. "rows" is the sending margin, so that each node is treated by the ties it sends; "columns" is the receiving margin; and "both" combines them. The two margins coincide for an undirected network, where all three options therefore agree. A two-mode network raises no such question, so "rows" and "columns" there are just the two nodesets.

Note that both the default and what "both" combines differ by function. to_normalised() defaults to "both", where it divides by the square root of the two denominators multiplied together, since that is the only rescaling that preserves a network's symmetry. to_proximity() defaults to "rows", the conventional profile for structural equivalence, and there "both" compares each node's sent and received ties together.

dyad

How the cells within the compared pair's own dyad are treated.

Four of the cells in any comparison are not like the others: \(i\)'s tie to \(j\), \(j\)'s tie to \(i\), and each node's self-tie. These cannot be compared where they lie the way the rest can. In column \(j\), node \(i\)'s entry is a tie to \(j\), but node \(j\)'s entry is its own self-tie: two different things in the same position. Two managers who happen to be tied to one another are not less structurally equivalent for it, but comparing those cells where they lie makes them look that way.

  • "exclude" drops all four cells, so that nodes are compared only on their ties to third parties. This is the strictest reading of structural equivalence, and the default for an undirected network.

  • "reciprocal" drops the self-ties, but compares \(i\)'s tie to \(j\) against \(j\)'s tie to \(i\), so that a reciprocated pair counts as alike there. This is the default for a directed network.

  • "complex" does the same, and additionally compares the two nodes' self-ties against each other. This is the default where the network has self-ties, since there they carry information.

  • "include" compares every cell where it lies, with no special treatment. Use it only where the diagonal genuinely holds comparable values. It is also the quickest, since it needs no pairwise walk.

By default the appropriate treatment is chosen from the network's format, as described above.

method

How the diagonal and the reciprocal ties are treated. "all" includes all information, "diag" excludes the diagonal (self-ties), "recip" excludes the diagonal but compares pairs' reciprocal ties, and "complex" compares pairs' reciprocal ties and their self ties. By default the appropriate method is chosen based on the network format.

These correspond to to_proximity()'s dyad argument, except that "recip" and "complex" append each node's tie to the other to profiles otherwise taken over the columns. to_proximity() instead keeps the profile and the appended cells on the same margin. The two therefore agree for an undirected network but not for a directed one.

Value

An object of the same class as the function was given, modified as explained in the function description, details, or section. Functions that split a network return a list of such objects.

Details

Not all functions have methods available for all object classes. Below are the currently implemented S3 methods:

               data.frame default igraph matrix network tbl_graph
to_correlation                  *             *                 *
to_cosine                       *             *
to_proximity            *       *      *      *       *         *

Node correlation

to_correlation() performs a Pearson pairwise correlation. It includes a switch: whereas for a two-mode network it performs a regular correlation, including all rows, for an undirected network it performs a correlation on a matrix with the diagonals removed, for a reciprocated network it includes the difference between reciprocated ties, and for complex networks it includes also the difference between the self ties in each pairwise calculation. This function runs in \(O(mn^2)\) complexity.

Node cosine

to_cosine() takes the cosine of the angle between each pair of the matrix's columns, without projecting it. It is to_proximity()'s "cosine" measure over the columns rather than the rows, and so accepts a two-mode network, where it describes the second mode.

References

On structural equivalence

Lorrain, Francois, and Harrison C. White. 1971. "Structural equivalence of individuals in social networks". The Journal of Mathematical Sociology 1(1): 49-80. doi:10.1080/0022250X.1971.9989788

See also

to_mode1(), which applies the same measures to a two-mode network, comparing nodes on their affiliations rather than on their ties.

Other modifications: modif_backbone, modif_direction, modif_from, modif_labels, modif_levels, modif_miss, modif_motifs, modif_paths, modif_permutation, modif_plexity, modif_project, modif_scope, modif_split, modif_weight

Examples

to_proximity(ison_algebra, "pearson")
#> 
#> ── # Proximities of M182 Algebra Class ─────────────────────────────────────────
#> # A signed, weighted, undirected network of 16 nodes and 120 ties
#> 
#> ── Ties 
#> # A tibble: 120 × 4
#>    from    to  weight  sign
#>   <int> <int>   <dbl> <dbl>
#> 1     1     2 -0.0515    -1
#> 2     1     3 -0.206     -1
#> 3     1     4  0.741      1
#> 4     1     5 -0.0809    -1
#> 5     1     6 -0.162     -1
#> 6     1     7 -0.133     -1
#> # ℹ 114 more rows
#> 
to_proximity(ison_adolescents, "jaccard")
#> ── # Proximities of The Adolescent Society ─────────────────────────────────────
#> # A labelled, weighted, undirected network of 8 nodes and 16 ties
#> 
#> ── Nodes 
#> # A tibble: 8 × 1
#>   name 
#>   <chr>
#> 1 Betty
#> 2 Sue  
#> 3 Alice
#> 4 Jane 
#> 5 Dale 
#> 6 Pam  
#> # ℹ 2 more rows
#> 
#> ── Ties 
#> # A tibble: 16 × 3
#>    from    to weight
#>   <int> <int>  <dbl>
#> 1     1     3  0.25 
#> 2     1     5  0.333
#> 3     1     6  0.333
#> 4     2     3  0.5  
#> 5     2     4  0.5  
#> 6     2     5  0.25 
#> # ℹ 10 more rows
#>