Besides the standard measures (see Getting started with
netmem), netmem implements measures that are hard to
find in other packages, several of them proposed in the last few years.
Each one is compared with the tables of the publication that defines it,
and the comparisons are kept in the folder dev/validation
of the GitHub
repository.
This vignette uses the Campnet network: the three people with whom each of the 18 people of a course interacted most (Borgatti et al., 2018).
library(netmem)
data(campnet)
A <- campnet$network
U <- pmax(A, t(A)) # Underlying graph
gender <- campnet$attributes$gender # 1 = woman, 2 = manRanking without choosing a centrality index
Every centrality index gives a ranking, and the rankings of different
indices often disagree. Schoch and Brandes (2016) show what they all
share: when the neighbours of u are also neighbours of
v, every standard index ranks v at least as
high as u. This neighbourhood inclusion is a
partial ranking, implied by the structure of the network before choosing
any index.
P <- neigh_inclusion(U) # P[u, v] = 1 when u is dominated by v
dominance_pairs(P)[c("comparable", "incomparable", "prop_comparable")]
#> $comparable
#> [1] 17
#>
#> $incomparable
#> [1] 136
#>
#> $prop_comparable
#> [1] 0.1111111Only 11% of the pairs of people are ranked by the structure itself. For the other 89%, the order depends on the index chosen. The rank of each person is an interval, from the lowest (one) to the highest rank that the person can take in a ranking consistent with the partial ranking. A wide interval means that the position of the person depends on the index:
dominance_ranks(P)
#> node min_rank max_rank width
#> 1 HOLLY 2 18 16
#> 2 BRAZEY 1 15 14
#> 3 CAROL 1 17 16
#> 4 PAM 3 18 15
#> 5 PAT 1 17 16
#> 6 JENNIE 1 17 16
#> 7 PAULINE 3 18 15
#> 8 ANN 1 17 16
#> 9 MICHAEL 4 18 14
#> 10 BILL 1 14 13
#> 11 LEE 1 15 14
#> 12 DON 2 16 14
#> 13 JOHN 1 18 17
#> 14 HARRY 2 16 14
#> 15 GERY 1 18 17
#> 16 STEVE 4 18 14
#> 17 BERT 3 17 14
#> 18 RUSS 1 18 17Two people with the same neighbours dominate each other. Removing these ties gives the strict dominance, whose layers go from the people who are not dominated by anyone to the most dominated:
strict <- P * (1 - t(P))
dominance_layers(strict)$layers
#> [[1]]
#> [1] "HOLLY" "PAM" "PAULINE" "MICHAEL" "JOHN" "GERY" "STEVE"
#> [8] "RUSS"
#>
#> [[2]]
#> [1] "CAROL" "PAT" "JENNIE" "ANN" "DON" "HARRY" "BERT"
#>
#> [[3]]
#> [1] "BRAZEY" "BILL" "LEE"preserved_order() checks whether an index respects the
partial ranking:
preserved_order(P, betweenness_centrality(U, digraph = FALSE))$preserved
#> [1] TRUEIn directed networks, Marmulla and Brandes (2026) show that each
family of indices preserves a different criterion. The indices of
status, such as in-degree and PageRank, preserve the inclusion of the
choices received (radial_in), whereas betweenness does
not:
D <- dir_inclusion(A, type = "radial_in")
preserved_order(D, colSums(A))$preserved
#> [1] TRUE
preserved_order(D, page_rank_centrality(A))$preserved
#> [1] TRUE
preserved_order(D, betweenness_centrality(A))
#> $preserved
#> [1] FALSE
#>
#> $violations
#> dominated dominating score_dominated score_dominating
#> 1 PAT PAM 39.5 32.5Pam receives the choices of everyone who chooses Pat, and more, yet Pat is more central than Pam by betweenness.
Overlapping categories
The measures of homophily, brokerage and structural holes assume that each person belongs to one category. Everett and Borgatti (2026) generalise them to memberships that overlap, such as groups, cliques or the time spent in several activities. Here the categories are the ten maximal cliques of the underlying graph, and several people belong to more than one:
cliques <- clique_max(U, min = 3)
K <- matrix(0, nrow(U), length(cliques),
dimnames = list(rownames(U), paste0("C", seq_along(cliques)))
)
for (k in seq_along(cliques)) {
K[cliques[[k]], k] <- 1
}
K
#> C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
#> HOLLY 1 0 0 0 0 0 0 0 0 0
#> BRAZEY 0 1 0 0 0 0 0 0 0 0
#> CAROL 0 0 0 1 1 0 0 0 0 0
#> PAM 0 0 0 1 0 1 1 0 0 0
#> PAT 0 0 0 0 1 0 0 0 0 0
#> JENNIE 0 0 0 0 0 1 0 0 0 0
#> PAULINE 0 0 0 1 1 0 1 0 0 0
#> ANN 0 0 0 0 0 1 1 0 0 0
#> MICHAEL 1 0 1 0 0 0 0 0 0 0
#> BILL 0 0 1 0 0 0 0 0 0 0
#> LEE 0 1 0 0 0 0 0 0 0 0
#> DON 1 0 1 0 0 0 0 0 0 0
#> JOHN 0 0 0 0 0 0 0 1 0 0
#> HARRY 1 0 1 0 0 0 0 0 0 0
#> GERY 0 0 0 0 0 0 0 1 1 0
#> STEVE 0 1 0 0 0 0 0 0 1 1
#> BERT 0 1 0 0 0 0 0 0 0 1
#> RUSS 0 0 0 0 0 0 0 1 1 1Each membership is divided by the number of categories of the person, so that every person counts once. The composition of the alters of each person gives how many of them, fractionally, belong to each clique, and the heterogeneity summarises it:
round(alter_composition(A, K), 2)
#> C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
#> HOLLY 0.5 0.00 0.5 0.33 1.00 0.33 0.33 0.00 0.00 0.00
#> BRAZEY 0.0 1.83 0.0 0.00 0.00 0.00 0.00 0.00 0.33 0.83
#> CAROL 0.0 0.00 0.0 0.67 1.33 0.33 0.67 0.00 0.00 0.00
#> PAM 0.0 0.00 0.0 0.33 0.33 1.50 0.83 0.00 0.00 0.00
#> PAT 1.0 0.00 0.0 0.50 0.50 1.00 0.00 0.00 0.00 0.00
#> JENNIE 0.0 0.00 0.0 0.33 1.00 0.83 0.83 0.00 0.00 0.00
#> PAULINE 0.0 0.00 0.0 0.83 1.50 0.33 0.33 0.00 0.00 0.00
#> ANN 0.0 0.00 0.0 0.67 0.33 1.33 0.67 0.00 0.00 0.00
#> MICHAEL 2.0 0.00 1.0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#> BILL 1.5 0.00 1.5 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#> LEE 0.0 1.83 0.0 0.00 0.00 0.00 0.00 0.00 0.33 0.83
#> DON 2.0 0.00 1.0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#> JOHN 0.0 0.00 0.0 0.33 0.33 0.00 0.33 0.83 0.83 0.33
#> HARRY 2.0 0.00 1.0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
#> GERY 0.5 0.33 0.5 0.00 0.00 0.00 0.00 0.33 0.67 0.67
#> STEVE 0.0 1.50 0.0 0.00 0.00 0.00 0.00 0.33 0.33 0.83
#> BERT 0.0 1.33 0.0 0.00 0.00 0.00 0.00 0.33 0.67 0.67
#> RUSS 0.0 0.83 0.0 0.00 0.00 0.00 0.00 0.50 0.83 0.83
round(alter_heterogeneity(A, K), 2)
#> HOLLY BRAZEY CAROL PAM PAT JENNIE PAULINE ANN MICHAEL BILL
#> 0.80 0.54 0.69 0.65 0.72 0.72 0.65 0.69 0.44 0.50
#> LEE DON JOHN HARRY GERY STEVE BERT RUSS
#> 0.54 0.44 0.80 0.44 0.82 0.65 0.69 0.74The E-I index and Yule’s Q with overlapping categories:
round(cbind(
ei = alter_homophily(A, K),
yule = alter_homophily(A, K, method = "yule")
), 2)
#> ei yule
#> HOLLY 0.67 0.44
#> BRAZEY -0.22 1.00
#> CAROL 0.33 1.00
#> PAM 0.41 0.94
#> PAT 0.67 0.78
#> JENNIE 0.44 1.00
#> PAULINE 0.41 0.94
#> ANN 0.33 1.00
#> MICHAEL 0.00 0.93
#> BILL 0.00 1.00
#> LEE -0.22 1.00
#> DON 0.00 0.93
#> JOHN 0.44 1.00
#> HARRY 0.00 0.93
#> GERY 0.67 0.69
#> STEVE 0.41 0.84
#> BERT 0.33 0.86
#> RUSS 0.52 0.86The brokerage roles of Gould and Fernandez (1989) become fractional, as each broker, sender and receiver might share several categories:
round(brokerage_roles(A, K), 2)
#> coordinator gatekeeper representative consultant liaison total
#> HOLLY 0.00 0.50 3.00 0.00 4.50 8
#> BRAZEY 0.00 0.00 0.00 0.00 0.00 0
#> CAROL 0.17 0.33 0.83 0.17 0.50 2
#> PAM 0.06 2.39 1.06 0.11 4.39 8
#> PAT 0.00 1.00 1.67 0.00 5.33 8
#> JENNIE 0.00 0.83 0.83 0.00 2.33 4
#> PAULINE 0.06 2.17 0.72 0.11 3.94 7
#> ANN 0.00 0.17 0.50 0.00 0.33 1
#> MICHAEL 0.00 2.00 0.50 0.00 1.50 4
#> BILL 0.00 0.00 0.00 0.00 0.00 0
#> LEE 0.83 1.17 0.00 0.00 0.00 2
#> DON 0.50 1.00 1.00 0.50 0.00 3
#> JOHN 0.00 0.00 0.00 0.00 0.00 0
#> HARRY 0.00 0.50 0.50 0.00 0.00 1
#> GERY 0.00 0.17 1.33 0.00 1.50 3
#> STEVE 0.00 1.44 1.22 0.00 2.33 5
#> BERT 0.00 0.83 1.17 0.00 1.00 3
#> RUSS 0.06 1.17 1.33 0.11 2.33 5Betweenness can be split by the category of the people who need the
brokers to reach the others. The column sums give how much the members
of each clique depend on people in between (Everett and Borgatti, 2026:
Table 6). The clique of Brazey, Lee, Steve and Bert (C2)
depends on them the most:
round(colSums(partition_centrality(A, K)), 1)
#> C1 C2 C3 C4 C5 C6 C7 C8 C9 C10
#> 21.0 138.2 32.0 14.2 17.2 23.5 16.2 43.2 35.8 44.8Finally, two alters of the same category might give access to the
same information even when they are not tied.
structural_holes() adds a tie of strength beta
between them. With gender as the category, the effective size falls most
for Pam, Gery and Pat, whose alters are of the same gender but not tied
to each other:
holes <- data.frame(
gender = gender,
original = structural_holes(A)$effective_size,
same_gender = structural_holes(A, gender, beta = 0.5)$effective_size,
row.names = rownames(A)
)
round(holes, 2)
#> gender original same_gender
#> HOLLY 1 3.86 3.50
#> BRAZEY 1 1.00 1.00
#> CAROL 1 2.00 1.50
#> PAM 1 3.88 2.00
#> PAT 1 3.57 2.29
#> JENNIE 1 2.33 1.67
#> PAULINE 1 3.86 3.14
#> ANN 1 1.60 1.30
#> MICHAEL 2 3.07 2.05
#> BILL 2 1.00 1.00
#> LEE 2 1.67 1.67
#> DON 2 2.14 2.07
#> JOHN 2 2.33 2.33
#> HARRY 2 1.75 1.67
#> GERY 2 2.90 1.48
#> STEVE 2 3.06 2.44
#> BERT 2 2.21 1.93
#> RUSS 2 2.79 1.80Q-analysis
The Q-analysis of Atkin (1974) describes a network through its maximal cliques (simplices) and how they share nodes. Two cliques are q-connected when a chain of cliques joins them, each sharing at least q + 1 nodes with the next. Freeman (1980) used it to study the structure of friendship networks.
q <- q_analysis(U)
q$q_table
#> q Q n Qbar obstruction
#> 1 3 3 3 0.0000000 2
#> 2 2 9 10 0.1000000 8
#> 3 1 8 15 0.4666667 7
#> 4 0 1 15 0.9333333 0
q$components$q1
#> component simplex
#> 1 1 HOLLY-MICHAEL-DON-HARRY
#> 3 1 MICHAEL-BILL-DON-HARRY
#> 2 2 BRAZEY-LEE-STEVE-BERT
#> 8 2 JOHN-GERY-RUSS
#> 9 2 GERY-STEVE-RUSS
#> 10 2 STEVE-BERT-RUSS
#> 4 3 CAROL-PAM-PAULINE
#> 5 3 CAROL-PAT-PAULINE
#> 6 3 PAM-JENNIE-ANN
#> 7 3 PAM-PAULINE-ANN
#> 11 4 HOLLY-PAM
#> 12 5 HOLLY-PAT
#> 13 6 PAT-JENNIE
#> 14 7 PAULINE-JOHN
#> 15 8 MICHAEL-GERYAt q = 0 the whole network is connected, at q = 1 the cliques of the instructors join those of Brazey and Lee, and at q = 3 only the three cliques of four people remain. The eccentricity measures how much a clique stands apart from the rest:
q$eccentricity
#> simplex dimension bottom eccentricity
#> 1 HOLLY-MICHAEL-DON-HARRY 3 2 0.3333333
#> 2 BRAZEY-LEE-STEVE-BERT 3 1 1.0000000
#> 3 MICHAEL-BILL-DON-HARRY 3 2 0.3333333
#> 4 CAROL-PAM-PAULINE 2 1 0.5000000
#> 5 CAROL-PAT-PAULINE 2 1 0.5000000
#> 6 PAM-JENNIE-ANN 2 1 0.5000000
#> 7 PAM-PAULINE-ANN 2 1 0.5000000
#> 8 JOHN-GERY-RUSS 2 1 0.5000000
#> 9 GERY-STEVE-RUSS 2 1 0.5000000
#> 10 STEVE-BERT-RUSS 2 1 0.5000000
#> 11 HOLLY-PAM 1 0 1.0000000
#> 12 HOLLY-PAT 1 0 1.0000000
#> 13 PAT-JENNIE 1 0 1.0000000
#> 14 PAULINE-JOHN 1 0 1.0000000
#> 15 MICHAEL-GERY 1 0 1.0000000Citation networks
A small corpus of 13 papers written by six authors, where
cites[p, q] = 1 when paper p cites paper
q (the network of Kuan, 2020: Fig. 2):
papers <- paste0("p", 1:13)
references <- list(
p4 = c("p1", "p2", "p3"), p5 = "p4", p6 = "p4", p7 = "p5",
p8 = c("p6", "p7"), p9 = "p7", p10 = "p7", p11 = "p7", p12 = "p8", p13 = "p8"
)
cites <- matrix(0, 13, 13, dimnames = list(papers, papers))
for (p in names(references)) {
cites[p, references[[p]]] <- 1
}
authors <- list(
p1 = "Ada", p2 = "Bo", p3 = c("Ada", "Cy"), p4 = c("Ada", "Bo"), p5 = "Cy",
p6 = c("Bo", "Di"), p7 = c("Cy", "Ed"), p8 = "Di", p9 = "Ed", p10 = c("Ed", "Flo"),
p11 = "Flo", p12 = c("Di", "Flo"), p13 = c("Ada", "Di")
)
X <- matrix(0, 6, 13, dimnames = list(c("Ada", "Bo", "Cy", "Di", "Ed", "Flo"), papers))
for (p in names(authors)) {
X[authors[[p]], p] <- 1
}Main path analysis
Main path analysis follows the flow of knowledge, from the cited
paper to the citing one (Hummon and Doreian, 1989), so it uses the
transpose of cites. The traversal weights count how many
paths between the first and the last papers go through each
citation:
flow <- t(cites)
dag_check(flow)$is_dag
#> [1] TRUE
spc <- traversal_weights(flow, method = "spc")
matrix_to_edgelist(spc$edge_weights, digraph = TRUE, valued = TRUE)
#> [,1] [,2] [,3]
#> [1,] "p1" "p4" "7"
#> [2,] "p2" "p4" "7"
#> [3,] "p3" "p4" "7"
#> [4,] "p4" "p5" "15"
#> [5,] "p4" "p6" "6"
#> [6,] "p5" "p7" "15"
#> [7,] "p6" "p8" "6"
#> [8,] "p7" "p8" "6"
#> [9,] "p7" "p9" "3"
#> [10,] "p7" "p10" "3"
#> [11,] "p7" "p11" "3"
#> [12,] "p8" "p12" "6"
#> [13,] "p8" "p13" "6"The global main path is the route with the largest total weight, and the key-route search starts from the arcs with the largest weights (Liu and Lu, 2012):
main_path(flow, method = "global")$routes
#> [[1]]
#> [1] "p1" "p4" "p5" "p7" "p8" "p12"
main_path(flow, method = "key_route", k = 2)$routes
#> [[1]]
#> [1] "p1" "p4" "p5" "p7" "p8" "p12"
#>
#> [[2]]
#> [1] "p2" "p4" "p5" "p7" "p8" "p12"The weights SPLC and SPNP (method = "splc",
"spnp") and the diagnostics of
main_path_diag() follow Liu et al. (2019) and Kuan
(2020).
Fractional counting
When the citations between papers are aggregated to citations between authors, full counting gives each coauthor of a paper the whole citation, so the total grows with the size of the teams. Fractional counting divides each citation among the authors, and the total remains the number of citations (Batagelj, 2020):
fractional_approach(cites, t(X), fractional = FALSE)
#> Ada Bo Cy Di Ed Flo
#> Ada 2 1 1 1 0 0
#> Bo 3 2 1 0 0 0
#> Cy 1 1 1 0 0 0
#> Di 1 2 1 3 1 0
#> Ed 0 0 3 0 2 0
#> Flo 0 0 2 1 2 0
round(fractional_approach(cites, t(X)), 2)
#> Ada Bo Cy Di Ed Flo
#> Ada 0.75 0.50 0.25 0.5 0.00 0
#> Bo 1.00 0.75 0.25 0.0 0.00 0
#> Cy 0.50 0.50 0.50 0.0 0.00 0
#> Di 0.25 0.75 0.50 1.5 0.50 0
#> Ed 0.00 0.00 1.25 0.0 0.75 0
#> Flo 0.00 0.00 0.75 0.5 0.75 0
sum(fractional_approach(cites, t(X)))
#> [1] 13
sum(cites)
#> [1] 13The fractional bibliographic coupling of two papers is not symmetric, and it can be made symmetric with one of six measures (here the geometric mean, that is, Salton’s cosine):
coupling <- fractional_approach(cites, approach = "bcoupling", symmetric = "geometric")
round(coupling[c("p8", "p9", "p10"), c("p8", "p9", "p10")], 2)
#> p8 p9 p10
#> p8 1.00 0.71 0.71
#> p9 0.71 1.00 1.00
#> p10 0.71 1.00 1.00Dominance among authors
The hyper-event dominance (Espinosa-Rada, 2026) compares authors
through the chain author, citing paper, cited paper, cited author, in
three dimensions: the papers written, the papers cited and the authors
cited. An author dominates another when the neighbourhood of the second
is included in that of the first in at least tau
dimensions:
H <- hyperevent_dominance(X, cites, tau = 2) # H[u, v] = 1 when u is dominated by v
H
#> Ada Bo Cy Di Ed Flo
#> Ada 0 0 0 0 0 0
#> Bo 1 0 0 0 0 0
#> Cy 0 0 0 0 0 0
#> Di 0 0 0 0 0 0
#> Ed 0 0 0 0 0 0
#> Flo 0 0 0 1 0 0
dominance_layers(H)$status
#> Ada Bo Cy Di Ed
#> "dominant" "dominated" "independent" "dominant" "independent"
#> Flo
#> "dominated"Ada dominates Bo and Di dominates Flo, while Cy and Ed are not comparable with anyone.
Multilevel and multiplex networks
The vignette Multilayer networks shows the functions for networks with several levels or several relations: the meta-matrix, the degree and k-core of multilevel networks, the mixed triad census of a network and a two-mode network, and the triad census of a directed and an undirected relation among the same people (Espinosa-Rada et al., 2024).
References
Atkin, R. H. (1974). Mathematical Structure in Human Affairs. Crane, Russak.
Batagelj, V. (2020). On fractional approach to analysis of linked networks. Scientometrics, 123(2), 621–633. https://doi.org/10.1007/s11192-020-03383-y
Borgatti, S. P., Everett, M. G. and Johnson, J. C. (2018). Analyzing Social Networks. Second edition. SAGE.
Espinosa-Rada, A. (2026). Network positions within scholars and intellectual networks. Journal of Informetrics, 20(3), 101854. https://doi.org/10.1016/j.joi.2026.101854
Espinosa-Rada, A., Bellotti, E., Everett, M. and Stadtfeld, C. (2024). Co-evolution of a socio-cognitive scientific network: A case study of citation dynamics among astronomers. Social Networks, 78, 92–108. https://doi.org/10.1016/j.socnet.2023.11.008
Everett, M. G. and Borgatti, S. P. (2026). Alter composition with overlapping group memberships. Social Networks, 85, 80–88. https://doi.org/10.1016/j.socnet.2025.12.001
Freeman, L. C. (1980). Q-analysis and the structure of friendship networks. International Journal of Man-Machine Studies, 12(4), 367–378. https://doi.org/10.1016/S0020-7373(80)80021-6
Gould, R. V. and Fernandez, R. M. (1989). Structures of mediation: A formal approach to brokerage in transaction networks. Sociological Methodology, 19, 89–126. https://doi.org/10.2307/270949
Hummon, N. P. and Doreian, P. (1989). Connectivity in a citation network: The development of DNA theory. Social Networks, 11(1), 39–63. https://doi.org/10.1016/0378-8733(89)90017-8
Kuan, C. H. (2020). Regarding weight assignment algorithms of main path analysis and the conversion of arc weights to node weights. Scientometrics, 124(1), 775–782. https://doi.org/10.1007/s11192-020-03468-8
Liu, J. S. and Lu, L. Y. Y. (2012). An integrated approach for main path analysis: Development of the Hirsch index as an example. Journal of the American Society for Information Science and Technology, 63(3), 528–542. https://doi.org/10.1002/asi.21692
Liu, J. S., Lu, L. Y. Y. and Ho, M. H. C. (2019). A few notes on main path analysis. Scientometrics, 119(1), 379–391. https://doi.org/10.1007/s11192-019-03034-x
Marmulla, G. and Brandes, U. (2026). Centrality in directed networks. Social Networks, 86, 23–34. https://doi.org/10.1016/j.socnet.2026.01.001
Schoch, D. and Brandes, U. (2016). Re-conceptualizing centrality in social networks. European Journal of Applied Mathematics, 27(6), 971–985. https://doi.org/10.1017/S0956792516000401
