These functions measure how well some proposed structure describes a network. Unlike the intrinsic properties in measure_features, each takes a structure from the user — a core-periphery mark, or a partition of the nodes — and returns how closely the observed network corresponds to it:

  • net_by_core() measures the correlation between a network and a core-periphery model with the same dimensions.

  • net_by_factions() measures the correlation between a network and a component model with the same dimensions.

  • net_by_modularity() measures the modularity of a network based on nodes' membership in defined clusters.

  • net_by_inconsistency() measures how far a partition's blocks depart from ideal block types.

These are the natural companions to the node_in_*() functions, which propose a structure; these say how good that proposal is. Where a partition is expected but none is given, the network is partitioned into two using node_in_partition().

Note that they are not on a common scale, and do not all run in the same direction, so they are not interchangeable:

measurecompares the network againstrangebetter
net_by_core()a core-periphery model-1 to 1higher
net_by_factions()a components model-1 to 1higher
net_by_modularity()the partition's communities-0.5 to 1 (at the default resolution)higher
net_by_inconsistency()ideal block types0 upwardslower

Compare partitions using one measure at a time.

net_by_core(
  .data,
  mark = NULL,
  variant = c("correlation", "ident", "ndiff", "diff"),
  coreness = NULL,
  direction = c("all", "out", "in"),
  method = NULL
)

net_by_factions(.data, membership = NULL)

net_by_modularity(.data, membership = NULL, resolution = 1)

net_by_inconsistency(.data, membership = NULL, blocks = c("nul", "com"))

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().

mark

A logical vector indicating which nodes belong to the core.

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.

coreness

Which method to use to calculate nodes' coreness. One of "correlation", "rich", "transition", or "hub"; see method_coreness for what each does. By default NULL, which uses "rich" for a weighted, directed, or two-mode network, since it is the only method that reads those properties directly, and "correlation" otherwise.

direction

One of "all" (the default), "out", or "in". For a directed network, "out" scores nodes on the ties they send and "in" on the ties they receive. Ignored for undirected and two-mode networks.

method

Deprecated. The former spelling of variant. Still accepted, but warns; please use variant instead.

membership

A character string naming an existing node attribute in the network, or a categorical vector of the same length as the number of nodes in the network where each element indicates the group membership of the corresponding node. While this may often be a vector created using node_in_*() functions, it can be any character vector that assigns nodes to groups or categories.

resolution

A proportion indicating the resolution scale. By default 1, which returns the original definition of modularity. The higher this parameter, the more smaller communities will be privileged. The lower this parameter, the fewer larger communities are likely to be found.

blocks

A character vector of permitted ideal block types, or a list-matrix giving the permitted types for each block position. By default c("nul", "com"), which is structural blockmodelling. See the section below.

Value

A network_measure numeric score.

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().

Core-periphery fit variants

For net_by_core(), which of the following to use to calculate the fit of the core assignment to a core-periphery model. "correlation" calculates the correlation between the empirical network and an ideal typical network, and "ident" calculates the Euclidean distances between the same. "ndiff", however, calculates how distinct the core and periphery groups are based on the difference in coreness scores between the least core-like member of the core and the most core-like member of the periphery. "diff" is similar to "ndiff", but multiplies the raw "ndiff" score by the square root of the size of the core, thus penalising large cores.

Core-Periphery

net_by_core() calculates the Pearson correlation between the given network, where the nodes in the core are assigned by some given mark, and an ideal typical core-periphery network with the same number of nodes in the core and the periphery.

Where mark is not given, it is calculated with node_is_core(), to which the coreness and direction arguments are passed. For a directed network the fit itself is measured on the symmetrised network, since the ideal it is compared against is symmetric.

Modularity

Modularity measures the difference between the number of ties within each community from the number of ties expected within each community in a random graph with the same degrees. At the default resolution it ranges between -0.5 and +1; a higher resolution can push it further below that floor. Modularity scores approaching +1 mean that ties only appear within communities, while negative scores mean that ties appear between communities more often than chance would predict. A score of 0 would mean that ties are half within and half between communities, as one would expect in a random graph.

Modularity faces a difficult problem known as the resolution limit (Fortunato and Barthélemy 2007). This problem appears when optimising modularity, particularly with large networks or depending on the degree of interconnectedness, can miss small clusters that 'hide' inside larger clusters. In the extreme case, this can be where they are only connected to the rest of the network through a single tie. To help manage this problem, a resolution parameter is added. Please see the argument definition for more details.

Blockmodelling

A blockmodel proposes that a partition reduces a network to a small number of positions, so that every block — the ties running from one position to another — is of some simple ideal type. net_by_inconsistency() measures how far the network departs from that proposal, by counting the ties that would have to be added or removed to make every block ideal, normalized by the number of cells. Lower is better: 0 means the partition fits perfectly.

This is a distance from an ideal image rather than a measure of fit — hence the name, and hence its running the opposite way to the rest of this page. Three consequences are worth knowing:

  • Its complement is not a proportion. The criterion mixes units: nul and com count cells, while reg counts empty rows and columns, and all are divided by the cell count. So do not read \(1 - x\) as the share of the network that the blockmodel gets right.

  • It is not bounded above by 1. That holds only for cell-counting vocabularies such as c("nul", "com"). With reg permitted it can exceed 1 — on ison_adolescents, blocks = "reg" over singleton positions reaches about 1.57.

  • The vocabularies behave very differently at fine partitions. Giving every node its own position scores 0 under c("nul", "com"), since each block is then a single cell and trivially ideal, but scores its worst under "reg", since each block then has an empty row and column.

For a correlation-scaled, higher-is-better reading of the common structural case, see net_by_factions(). The two are related but not equivalent: net_by_factions() fixes the image — complete on the diagonal, null off it — whereas net_by_inconsistency(blocks = c("nul", "com")) lets each block take whichever of the two ideals fits it better, and so is more permissive.

The ideal types are:

nul

a null block, containing no ties.

com

a complete block, containing every possible tie.

reg

a regular block, in which every row and every column has at least one tie, though not necessarily all of them.

rdo, cdo

a row- or column-dominant block, containing at least one complete row or column.

dnc

"do not care": a block left unconstrained.

blocks is a vocabulary rather than an assignment: each block is scored at the lowest inconsistency of any permitted type, and the results summed. Any subset may be given, and the two conventional choices are c("nul", "com") for structural equivalence and c("nul", "reg") for regular equivalence.

Note that permitting more types can only lower the criterion, since each block gains more ways to be satisfied. The size of the vocabulary is therefore itself a modelling choice, and criterion values are comparable across partitions only when the same vocabulary is used for each.

For fully generalized blockmodelling, pass a g by g list-matrix naming the types permitted at each position separately, e.g. reg on the diagonal and nul off it for a "cohesive positions" model.

References

On core-periphery

Borgatti, Stephen P., and Martin G. Everett. 2000. “Models of Core/Periphery Structures.” Social Networks 21(4):375–95. doi:10.1016/S0378-8733(99)00019-2

On modularity

Newman, Mark E.J. 2006. "Modularity and community structure in networks", Proceedings of the National Academy of Sciences 103(23): 8577-8696. doi:10.1073/pnas.0601602103

Murata, Tsuyoshi. 2010. "Modularity for Bipartite Networks". In: Memon, N., Xu, J., Hicks, D., Chen, H. (eds) Data Mining for Social Network Data. Annals of Information Systems, Vol 12. Springer, Boston, MA. doi:10.1007/978-1-4419-6287-4_7

On generalized blockmodelling

Doreian, Patrick, Vladimir Batagelj, and Anuska Ferligoj. 2005. Generalized Blockmodeling. Cambridge: Cambridge University Press. doi:10.1017/CBO9780511584176

Examples

net_by_core(ison_adolescents)
#> # Core-periphery correlation [-1, 1]
#> [1] -0.133
net_by_core(ison_southern_women)
#> # Core-periphery correlation [-1, 1]
#> [1] -0.274
  net_by_factions(ison_southern_women)
#> # Factional correlation [-1, 1]
#> [1] -0.156
net_by_modularity(ison_adolescents, 
  node_in_partition(ison_adolescents))
#> # Modularity [-0.5, 1]
#> [1] -0.32
net_by_modularity(ison_southern_women, 
  node_in_partition(ison_southern_women))
#> # Modularity [-0.5, 1]
#> [1] -0.456
net_by_inconsistency(ison_hightech, node_in_regular(ison_hightech))
#> # Blockmodel inconsistency [0, Inf)
#> [1] 0.326
# a regular-equivalence vocabulary instead of a structural one
net_by_inconsistency(ison_hightech, node_in_structural(ison_hightech), 
       blocks = c("nul", "reg"))
#> # Blockmodel inconsistency [0, Inf)
#> [1] 0