These functions combine an appropriate node_x_*() function together with methods for calculating the hierarchical clusters provided by how alike nodes' profiles are.

  • node_in_equivalence() assigns nodes membership based on their equivalence with respective to some motif/class. The following functions call this function, together with an appropriate motif.

  • node_in_structural() assigns nodes membership based on their having equivalent ties to the same other nodes.

  • node_in_regular() assigns nodes membership based on their having equivalent patterns of ties to equivalent others.

  • node_in_automorphic() assigns nodes membership based on their having equivalent distances to other nodes.

  • node_in_motif() assigns nodes membership based on their participating in local structures at similar rates.

A plot() method exists for investigating the dendrogram of the hierarchical cluster and showing the returned cluster assignment.

node_in_equivalence(
  .data,
  motif,
  k = c("silhouette", "elbow", "strict"),
  cluster = c("hierarchical", "concor"),
  distance = NULL,
  max_k = 8L,
  proximity = "pearson",
  Kmax = NULL
)

node_in_structural(
  .data,
  k = c("silhouette", "elbow", "strict"),
  cluster = c("hierarchical", "concor"),
  distance = NULL,
  max_k = 8L,
  proximity = "pearson",
  Kmax = NULL
)

node_in_regular(
  .data,
  k = c("silhouette", "elbow", "strict"),
  cluster = c("hierarchical", "concor"),
  distance = NULL,
  max_k = 8L,
  regularity = c("rolesim", "rege"),
  decay = 0.15,
  beta = NULL,
  Kmax = NULL
)

node_in_motif(
  .data,
  k = c("silhouette", "elbow", "strict"),
  cluster = c("hierarchical", "concor"),
  distance = NULL,
  max_k = 8L,
  proximity = "pearson",
  Kmax = NULL
)

node_in_automorphic(
  .data,
  k = c("silhouette", "elbow", "strict"),
  cluster = c("hierarchical", "concor"),
  distance = NULL,
  max_k = 8L,
  proximity = "pearson",
  Kmax = NULL
)

node_in_block(
  .data,
  k = 2L,
  blocks = c("nul", "com"),
  times = NULL,
  search = c("tabu", "iterated")
)

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

motif

A matrix returned by a node_x_*() function.

k

Typically a character string indicating which method should be used to select the number of clusters to return. By default "silhouette", other options include "elbow" and "strict". "strict" returns classes with members only when strictly equivalent. "silhouette" and "elbow" select classes based on the distance between clusters or between nodes within a cluster. Fewer, identifiable letters, e.g. "e" for elbow, is sufficient. Alternatively, if k is passed an integer, e.g. k = 3, then all selection routines are skipped in favour of this number of clusters.

cluster

Character string indicating whether clusters should be clustered hierarchically ("hierarchical") or through convergence of correlations ("concor"). Fewer, identifiable letters, e.g. "c" for CONCOR, is sufficient. "cosine" is deprecated; use proximity = "cosine" instead.

distance

Character string indicating which distance metric to pass on to stats::dist to compare nodes a second time, on their profiles of dissimilarities to all nodes. By default NULL, so that the proximities are clustered directly. Options include "euclidean", "maximum", "manhattan", "canberra", "binary", and "minkowski". Fewer, identifiable letters, e.g. "e" for Euclidean, is sufficient. Before v1.1.0 the default was "euclidean", so pass that to reproduce earlier results. Ignored when cluster = "concor".

max_k

Integer indicating the maximum number of (k) clusters to evaluate. Ignored when k = "strict" or a discrete number is given for k.

proximity

Character string indicating how nodes' profiles should be compared, passed on to manynet::to_proximity(). By default "pearson", their correlation, but any measure offered there can be used, e.g. "cosine", "ruzicka", "overlap", "euclidean", or "hamming". Note that "jaccard" dichotomises a valued census; "ruzicka" is the weighted counterpart that keeps the counts. The proximities themselves are in the proximity element of the clustering, e.g. attr(node_in_structural(.data), "hc")$proximity, or can be made with manynet::to_proximity() from any census, using across = "rows" and dyad = "include". Ignored when cluster = "concor". "asis" clusters a motif that is already a node-by-node similarity. node_in_regular() does not take it, since regularity_*() already returns a node-by-node similarity, which is clustered as it is.

Kmax

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

regularity

Character string indicating which algorithm should be used to calculate how regularly equivalent nodes are. By default "rolesim"; "rege" is also available. Fewer, identifiable letters, e.g. "ro" for RoleSim, is sufficient. See regularity_rolesim() and regularity_rege() for how they differ.

decay

A proportion between 0 and 1 giving how much of a contribution survives each additional step of distance or walk length. Lower values discount more steeply, so that only nearby others count; higher values discount less, so that longer walks continue to contribute. The measures that take a decay differ in what they discount and in what value leaves the measure in its most familiar form, so each documents its own default.

beta

Deprecated; use decay instead.

blocks

A character vector of permitted ideal block types, or a list-matrix giving the permitted types per block position. See net_by_inconsistency() for the available types.

times

Integer number of steps the search takes. By default the number of nodes times the number of positions. For search = "tabu" this is the most steps that each of its runs may take, since a run also ends once it stops improving.

Which method to use to search the space of partitions. One of "tabu" (the default) or "iterated"; see method_search for what each does.

Value

A node_member character vector the length of the nodes in the network, of group memberships "A", "B", etc for each node. If the network is labelled, then the assignments will be labelled with the nodes' names.

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

Regular equivalence

Two nodes are regularly equivalent if each has ties to the same kinds of others, even where those others are not the same individuals and are not equally numerous. A manager with three subordinates and a manager with ten are regularly equivalent, because what makes them alike is that they both have subordinates, not how many or which.

The definition is recursive: nodes are equivalent if their alters are equivalent, whose equivalence depends in turn on their alters. node_in_regular() therefore computes a similarity matrix by iterating that definition to a fixed point, and then clusters that similarity directly, rather than comparing nodes' profiles first as the other functions here do. Give distance to compare the nodes' similarities a second time.

Note that this differs from node_in_motif(), which compares nodes on how often they appear embedded in local structures. Two nodes can have very similar triad profiles without being regularly equivalent, and vice versa, since a motif census counts a node's local configurations while regular equivalence asks who its alters are.

Motif equivalence

Where the other functions here compare nodes on whom they are tied to, node_in_motif() compares them on what kinds of local structure they sit in, by clustering a census of the triads (or, for two-mode networks, tetrads) each node participates in.

Note that the census counts the types of motif a node takes part in, and not the position it holds within them. In the path \(i \rightarrow k \rightarrow j\), for example, all three nodes return a profile of one 021C triad, although \(i\) sends, \(k\) mediates and \(j\) receives. This is therefore neither Burt's role equivalence, which distinguishes those positions, nor the orbit-aware census of Ortmann and Brandes, which netrics does not yet offer.

What it captures is similarity of local embedding. It is well suited to distinguishing nodes that sit in dense, closed neighbourhoods from those that bridge open ones, but it is not regular equivalence: see node_in_regular() for that.

This function was called node_in_regular() prior to version 1.0.0.

Direct blockmodelling

The other functions here are indirect: they build a similarity between nodes, cluster it, and read a partition off the result. node_in_block() is direct. It searches the space of partitions for the one that best fits an ideal block structure, scoring each candidate with net_by_inconsistency() and keeping whichever is most consistent.

The advantage is that the criterion being optimised is the one you actually care about, rather than a similarity that stands in for it, and that ideal types other than "null and complete" become available — blocks = c("nul", "reg") searches directly for a regular-equivalence blockmodel. The cost is that the number of positions k must be chosen in advance, and that the search is stochastic: it begins from random partitions, so repeated runs may return different partitions and a longer search is more likely to find a good one.

By default the search is a tabu search, search_tabu(), which lets the positions take any size, and so can find a small core or one large position where the network has them. search = "iterated" uses search_iterated(), the only search available prior to version 1.1.0. It is quicker on a large network, but it holds the positions at near-equal size. Set a seed for reproducibility, and compare runs with net_by_inconsistency().

References

On role equivalence

Burt, Ronald S. 1990. "Detecting role equivalence". Social Networks 12(1): 83-97. doi:10.1016/0378-8733(90)90023-3

On the orbit-aware census

Ortmann, Mark, and Ulrik Brandes. 2017. "Efficient orbit-aware triad and quad census in directed and undirected graphs". Applied Network Science 2(1): 13. doi:10.1007/s41109-017-0027-2

On direct blockmodelling

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

Examples

(nse <- node_in_structural(ison_algebra))
#> 7 groups
#>   V1    V2    V3    V4    V5    V6    V7    V8    V9    V10   V11   V12   V13  
#> 1 A     B     C     A     D     D     B     B     E     E     F     A     B    
#> # ... and 3 more values from this nodeset. Use `print_all(...)` to print all values.
(nre <- node_in_regular(ison_southern_women))
#> 7 groups
#>   Evelyn Laura Theresa Brenda Charlotte Frances Eleanor Pearl Ruth  Verne Myra 
#> 1 A      A     A       A      B         B       B       C     B     B     B    
#> # ... and 7 more values from this nodeset. Use `print_all(...)` to print all values.
#>   E1    E2    E3    E4    E5    E6    E7    E8    E9    E10   E11   E12   E13  
#> 1 D     D     E     E     F     F     F     F     F     E     G     E     D    
#> # ... and 1 more values from this nodeset. Use `print_all(...)` to print all values.
(nme <- node_in_motif(ison_southern_women, cluster = "concor"))
#> 8 groups
#>   Evelyn Laura Theresa Brenda Charlotte Frances Eleanor Pearl Ruth  Verne Myra 
#> 1 A      B     A       B      C         C       D       D     D     D     C    
#> # ... and 7 more values from this nodeset. Use `print_all(...)` to print all values.
#>   E1    E2    E3    E4    E5    E6    E7    E8    E9    E10   E11   E12   E13  
#> 1 E     E     F     E     F     F     G     H     G     E     E     F     E    
#> # ... and 1 more values from this nodeset. Use `print_all(...)` to print all values.
if(require("sna", quietly = TRUE)){
(nae <- node_in_automorphic(ison_southern_women,
  k = "elbow"))
}
#> 
#> Attaching package: ‘statnet.common’
#> The following objects are masked from ‘package:base’:
#> 
#>     attr, order, replace
#> 
#> ‘network’ 1.20.0 (2026-02-06), part of the Statnet Project
#> * ‘news(package="network")’ for changes since last version
#> * ‘citation("network")’ for citation information
#> * ‘https://statnet.org’ for help, support, and other information
#> sna: Tools for Social Network Analysis
#> Version 2.8 created on 2024-09-07.
#> copyright (c) 2005, Carter T. Butts, University of California-Irvine
#>  For citation information, type citation("sna").
#>  Type help(package="sna") to get started.
#> 3 groups
#>   Evelyn Laura Theresa Brenda Charlotte Frances Eleanor Pearl Ruth  Verne Myra 
#> 1 A      A     A       A      A         A       A       B     B     B     B    
#> # ... and 7 more values from this nodeset. Use `print_all(...)` to print all values.
#>   E1    E2    E3    E4    E5    E6    E7    E8    E9    E10   E11   E12   E13  
#> 1 A     A     A     A     A     A     A     B     B     C     C     C     C    
#> # ... and 1 more values from this nodeset. Use `print_all(...)` to print all values.
(nbm <- node_in_block(ison_adolescents, k = 3))
#> 3 groups
#>   Betty Sue   Alice Jane  Dale  Pam   Carol Tina 
#> 1 C     B     B     C     C     C     A     A    
net_by_inconsistency(ison_adolescents, nbm)
#> # Blockmodel inconsistency [0, Inf)
#> [1] 0.143