These functions calculate how core-like each node is, returning both a continuous coreness score and a core/periphery split that node_is_core(), node_by_core() and node_in_core() then use.

  • coreness_correlation() fits the network to an ideal core-periphery pattern by correlation.

  • coreness_rich() ranks nodes by strength and cuts where the tie weight to higher-ranked neighbours peaks.

  • coreness_transition() scores nodes with a transition function whose sharpness and core size are free parameters.

  • coreness_hub() scores nodes by how well they send to and receive from the core, which lets core and periphery differ by tie direction.

They differ in what they can use. coreness_rich() and coreness_hub() read tie direction and tie weights directly. coreness_correlation() and coreness_transition() compare the network against a symmetric ideal, so they symmetrise a directed network first and report that they have done so.

coreness_correlation(.data, direction = c("all", "out", "in"), starts = 5L)

coreness_rich(.data, direction = c("all", "out", "in"))

coreness_transition(
  .data,
  direction = c("all", "out", "in"),
  alpha = seq(0.2, 0.8, 0.2),
  beta = seq(0.2, 0.8, 0.2)
)

coreness_hub(.data, direction = c("all", "out", "in"))

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

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.

starts

Integer number of starting points for the search, at most 9. By default 5. The starting points are fixed rather than random, so that two calls on the same network return the same answer.

alpha

Numeric vector of boundary sharpness values between 0 and 1, to aggregate over. By default seq(0.2, 0.8, 0.2).

beta

Numeric vector of core size values between 0 and 1, to aggregate over. By default seq(0.2, 0.8, 0.2).

Value

A list with two elements:

  • coreness: a numeric vector between 0 and 1, one value per node, for how core-like each node is.

  • core: a logical vector, one value per node, TRUE for the core.

coreness_hub() adds out_core and in_core, the two core sets that a directed core-periphery structure distinguishes.

Correlation

Borgatti and Everett's continuous model gives each node a coreness \(c_i\) between 0 and 1, and compares the network against the ideal pattern \(c_i c_j\) in which two nodes are tied to the extent that both are core: $$\rho = \text{cor}(A_{ij}, c_i c_j), i \neq j$$ The coreness vector that maximises \(\rho\) is the fitted model. Self-ties are excluded from the correlation, since no node is tied to itself and including the diagonal pulls every coreness toward zero.

The problem is not convex, so the search is run from several starting points, ordered by degree, and the best fit is kept. A weighted network is fitted to its weights, which means that the ideal pattern is read as how strongly two core nodes should be tied. To fit the pattern of ties instead of their weights, use manynet::to_unweighted() first.

The search has one free value per node, so its cost grows quickly with the size of the network. On a large network, lower starts, or use coreness_rich(), which needs no search at all.

Rich-core

Ma and Mondragon rank the nodes by strength, from strongest to weakest, and give each node the total weight of its ties to nodes that rank above it: $$\sigma_i^+ = \sum_{j : r_j < r_i} w_{ij}$$ Walking down the ranking, \(\sigma^+\) rises while the nodes added are still tied to those already above them, and falls once they are not. The rank at which it peaks is the boundary of the rich core.

The method needs no parameters and no optimisation, and it reads tie weights and tie direction directly, which makes it the method this package uses by default for a weighted, directed, or two-mode network. For a two-mode network the nodes of both modes are ranked together, so the core may span both.

Note that the core it finds is one whose members are tied to each other. Where a directed network instead has one set that sends and a different set that receives, \(\sigma^+\) never rises, and the method returns a core of one or two nodes. Use coreness_hub() for that structure, which keeps the two sets apart rather than trying to merge them.

A rich core is not a rich club, which is why this method is not named for one. A rich club requires the high-degree nodes to be densely tied to one another, and net_by_richclub() measures that density. A rich core only marks the rank at which nodes stop linking upward, so a network can have a rich core whose members are not densely tied. The rich core also needs no null model, where the rich-club coefficient does, since that coefficient rises with degree even in a random network.

Transition

Rombach and colleagues score the node at rank \(m\) with a transition function $$C_m = \frac{1}{1 + \exp(-(m - N\beta)\tan(\pi\alpha/2))}$$ where \(\alpha\) sets how sharp the boundary between core and periphery is, from fuzziest at 0 to a clean step at 1, and \(\beta\) sets how large the core is, from every node at 0 to none at 1. The ordering that maximises the core quality \(R = \sum_{ij} A_{ij} C_i C_j\) is the fitted model.

No single \(\alpha\) and \(\beta\) is right for every network, so the score is aggregated over a grid of both, weighting each by the core quality it achieves, and scaled so that the most core-like node is 1.

Hub

In a directed network a node can be core in whom it reaches and peripheral in who reaches it. Elliott and colleagues therefore keep two core sets rather than one: an out-core of nodes that send to the core, and an in-core of nodes that receive from it.

The two are read from the hub and authority scores that node_by_hub() and node_by_authority() already provide: a hub is a node that points to good authorities, and an authority is a node that good hubs point to, which is the same mutual definition the two core sets have. Each set is then cut by the same rule the other methods use. With direction = "all" the returned coreness is the geometric mean of the two scores, and the core is the set of nodes in both.

References

On the correlation method

Borgatti, Stephen P., and Martin G. Everett. 2000. "Models of core/periphery structures". Social Networks 21(4): 375-395. doi:10.1016/S0378-8733(99)00019-2

Lip, Sean Z. W. 2011. "A fast algorithm for the discrete core/periphery bipartitioning problem". doi:10.48550/arXiv.1102.5511

On the rich-core method

Ma, Athen, and Raul J. Mondragon. 2015. "Rich-cores in networks". PLoS ONE 10(3): e0119678. doi:10.1371/journal.pone.0119678

On the transition method

Rombach, Puck, Mason A. Porter, James H. Fowler, and Peter J. Mucha. 2017. "Core-periphery structure in networks (revisited)". SIAM Review 59(3): 619-646. doi:10.1137/17M1130046

On the hub method

Elliott, Andrew, Angus Chiu, Marya Bazzi, Gesine Reinert, and Mihai Cucuringu. 2020. "Core-periphery structure in directed networks". Proceedings of the Royal Society A 476(2241): 20190783. doi:10.1098/rspa.2019.0783

See also

Other methods: method_regularity

Examples

coreness_correlation(ison_adolescents)
#> $coreness
#>     Betty       Sue     Alice      Jane      Dale       Pam     Carol      Tina 
#> 0.0650368 0.6515254 1.0000000 0.3979140 0.6172661 0.4120254 0.0000000 0.0000000 
#> 
#> $core
#> [1] FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE
#> 
coreness_rich(ison_networkers)
#> $coreness
#>        Lin Freeman         Doug White          Ev Rogers       Richard Alba 
#>       1.0000000000       0.4009705248       0.0023364486       0.0990294752 
#>      Phipps Arabie Carol Barner-Barry        Gary Coombs       Russ Bernard 
#>       0.0255212078       0.0630841121       0.0075485262       0.5174335011 
#>          John Boyd           Ron Burt        Pat Doreian     Claude Fischer 
#>       0.0832135155       0.1132278936       0.2640186916       0.0316319195 
#>       Brian Foster   Mark Granovetter   Maureen Hallinan       Paul Holland 
#>       0.0107836089       0.0318116463       0.0620057513       0.0774622574 
#>        Jack Hunter     Davor Jedlicka   Charles Kadushin         Ed Laumann 
#>       0.0742271747       0.0549964055       0.0239036664       0.0005391804 
#>      Sam Leinhardt        Joel Levine            Nan Lin       Nick Mullins 
#>       0.0057512581       0.0452911574       0.0136592380       0.2129762761 
#>          Don Ploch    Nick Poushinsky      Steve Seidman      John Sonquist 
#>       0.0210280374       0.0235442128       0.1083752696       0.0000000000 
#>      Barry Wellman           Al Wolfe        Sue Freeman         Lee Sailer 
#>       0.6252695902       0.1063982746       0.3738317757       0.3375269590 
#> 
#> $core
#>  [1]  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
#> [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> [25] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE
#> 
coreness_transition(ison_adolescents)
#> $coreness
#> [1] 0.3019575 0.9622348 1.0000000 0.6262096 0.8917447 0.7828835 0.3400829
#> [8] 0.0000000
#> 
#> $core
#> [1] FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE
#> 
coreness_hub(ison_networkers)
#> $coreness
#>  [1] 1.000000000 0.567671811 0.005634952 0.111812047 0.020660080 0.095994085
#>  [7] 0.017708648 0.625318882 0.107039476 0.127999324 0.358597695 0.053456745
#> [13] 0.012309808 0.048695416 0.124465321 0.117969155 0.104618345 0.080756776
#> [19] 0.020806891 0.000000000 0.015220081 0.056388396 0.020431138 0.275129846
#> [25] 0.026231141 0.054356232 0.139529296 0.000000000 0.705799552 0.159437663
#> [31] 0.394717426 0.482473568
#> 
#> $core
#>  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#> [13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
#> [25]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
#> 
#> $out_core
#>  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#> [13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
#> [25]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#> 
#> $in_core
#>  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#> [13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
#> [25]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
#>