node_is_mentor() on two-mode networks by selecting the elites within each modenode_by_constraint() on 2mode via matrix algebra (90x faster on n=1000)
node_by_hierarchy()node_by_redundancy(), node_by_effsize(), and node_by_efficiency()
on 2mode by vectorising the redundancy (10-20x faster on n=1000)node_by_constraint(), node_by_hierarchy(), and node_by_redundancy()
on multilevel networks, by treating them as one-mode as node_by_effsize() doescoreness_hub() on two-mode networks by reading the degrees over all nodesnode_x_clique() and node_x_percolation() by finding 2mode cliques
and their incidence without a loop over cliquesnode_x_accuracy() for the confusion matrix of each reporter's view
of a CSS against an ideal, by default its LAS (closes #37)node_by_accuracy() and net_by_accuracy() for how well reporters' views
of a CSS on average agree with an ideal (closes #37)net_by_robustness() for how the giant component shrinks as nodes are removed (closes #42)
node_measure a vector will target nodes by these valuesnode_measure to attack=curve attributenode_is_neighbor() to take a cutoff, marking every node within that distance of the given nodenode_in_community() to also consider node_in_leiden() and node_in_partition() for signed networksnode_in_faction() to read signs rather than set negative ties aside
"hamming" counts negative ties within factions and the positive ties between them"phi" correlates each pair's sign with whether it shares a faction"modularity" maximises signed modularitynode_in_leiden() taking a negative default resolution on a negative-dominant signed network021D_f.ft300_++-021D_!!= for categories or 021D_>>< for ordered valuesnet_x_tetrad() takes 0.05s rather than 7s for 100 nodes, and 0.5s for 1000 nodes, which was not feasible beforenode_x_tetrad() takes 0.1s rather than 20s for 100 nodes, and under 1s for 1000 nodesnode_x_triad() takes 0.07s rather than 2.4s for 1000 nodesnet_x_dyad(), node_x_dyad(), and net_x_triad() were already fast and remain so*_x_tetrad() never reporting U4 lines, which were counted as D4net_x_tetrad() counting each tie twice, which mislabelled and dropped tetradsnode_x_dyad() counting each node's dyad with itself as Nullnode_x_dyad() dropping ties weighted below 1, which net_x_dyad() countednet_x_triad(), net_x_mixed() defunct"moran" to the assortativity options of net_by_homophily() and node_by_homophily()
net_by_homophily() returns global Moran's I, which net_by_spatial() also givesnode_by_homophily() returns local Moran's I (Anselin 1995), which sums to the global value times the total tie weightnet_by_meshedness() for Kansky's alpha index, the number of independent cycles relative to the most a planar network could havetie_by_diversity() for the diversity of the nodes that each tie joins, with the same diversity options as node_by_diversity() (closes #44)node_by_power() failing in the matrix solver where the exponent has no solutionnet_by_core() and net_by_divergence() comparing the network with an ideal whose core and periphery were swappednet_by_smallworld() to compare clustering with a (ring) lattice of the network's own densitynet_by_modularity() to return signed modularity (Gómez, Jensen, and Arenas 2009) for signed networks
net_by_core()mutate_nodes() instead of mutate(){manynet} floor to 2.3.4
{manynet}'s owntie_is_path()
tie_is_multiple() documentation to distinguish from manynet::tie_is_parallel()net_by_upperbound(), net_x_hierarchy(), and node_by_distance() erroring on a signed 'stocnet'
node_by_distance() scaling every distance to 0 where some node cannot be reached
node_by_diversity() to not include ego when measuring alter diversity (closes #39)
NAnode_by_information(), net_by_spatial() etc by
replacing to_multilevel() with manynet::to_onemode() to create square matricesmembership= to net_by_diversity() for mean diversity by group weighted by sizemode_by_eigenvector() erroring on multilevel networks (closes #23)variant= to node_by_transitivity() for Barrat, Onnela, or Zhang-Horvath weighted clustering
variant = "watts" keeps the unweighted resultnode_by_flow()
from= and to= for the maximum flow from or to a given nodenet_by_adhesion() now reads tie weights as capacities, returning weighted minimum cut
net_by_divergence() for networks' Hamming, Jaccard, or portrait divergence
ideal= takes a network or any manynet::create_*() or manynet::generate_*() functionnet_by_linkdensity() for the partition density of a tie membershipNA for groups beyond the 702ndnode_in_faction() for the k groups, of any size, that come closest to separate cliques
variant= scores the fit by "hamming" (default), "phi", or "modularity"search= to node_in_block() for searching by "tabu" (default) or "iterated"
search = "iterated" to reproduce themtie_in_community() for link communities (Ahn et al. 2010), which group ties rather than nodes (closes #20)
node_in_partition(), node_in_regular() etc by
replacing to_multilevel() with manynet::to_onemode() to create square matricesnode_in_equivalence(), node_in_structural(), node_in_motif(), and node_in_automorphic() now cluster the proximities between nodes' profiles directly, as documented and as sna::equiv.clust() doesdistance = "euclidean" to reproduce themproximity= to choose how profiles are compared, by default "pearson", from any measure in manynet::to_proximity(), e.g. "cosine", "ruzicka", or "overlap"distance= is now NULL by default; naming a distance compares nodes a second time on their dissimilarities, as before"count" or "crossmin" are subtracted from the largest proximity, with a message, rather than returning negative merge heightsnode_in_regular() now clusters the regularity_*() similarity directlycluster = "cosine" and cluster_cosine() in favour of proximity = "cosine"cluster_hierarchical() now also returns the proximities it clustered as $proximitynode_in_automorphic() erroring with k = "elbow" on weighted or unconnected networks
node_in_roulette(), with some implications for node_in_block()
groups= to accept a vector of group sizesattribute= and balance= to mix groups by a node attributedecay= to discount ties from earlier waves or times, by default uniform?member_community_modular, ?member_community_spread, and ?member_community_partition replace ?member_community_non?member_community now compares all the algorithms in one tablesearch_tabu() and search_iterated() for finding membership that minimises a costnet_x_stability() miscounting the ties that changed between networks
== bound after *, so it counted every absent tie, including self-ties, as changednet_x_correlation() requiring a second network (closes #27)
net_x_change() and net_x_stability() on networks with missing tiesnode_x_path() on weighted networks to return shortest path lengths (Opsahl et al. 2010)
node_x_alters(), thanks @RWKrause (closes #39)
direction= for out, in, reciprocated, or all (default) altersWeightedSum, each alter's value times the strength of the tie to itNA, also if categoricalnode_x_percolation() for overlapping communities by clique percolation (Palla et al. 2005) (closes #21)node_by_homophily() issues
net_by_homophily() discarding tie weights before Geary's C
net_by_spatial() erroring on a two-mode network
net_by_spatial() propagating missing valuesnet_by_diversity() and node_by_diversity() erroring on a factor attributenode_in_leiden() issues
resolutionnode_in_community(), node_in_spinglass() and node_in_fluid()
treating a weakly connected directed network as unconnectednode_in_partition() returning a split it had already improved upon
start= for a random rather than a node-order initialisation{manynet} floor to 2.3.1, retiring to_ties() and net_waves() shimsnode_is_fold() erroring on signed networks (closes #25)node_is_independent() and node_is_core() erroring on multilevel networks (closes #26)tie_is_transitive(), tie_is_triplet() and tie_is_cyclical() erroring on signed networks (closes #25)tie_is_max() and tie_is_min() to accept a numeric vector, and to name what they marktie_is_path() to name from and to where either is missing (closes #26)node_by_closeness(), node_by_harmonic(), node_by_reach(), node_by_decay(),
node_by_integration(), node_by_radiality(), node_by_eccentricity(), node_by_vitality(),
node_by_betweenness(), node_by_induced(), node_x_path()net_by_closeness(), net_by_betweenness(), net_by_connectedness(), net_by_reach(),
net_by_harmonic(), net_by_decay(), net_by_integration()mode_by_closeness(), mode_by_betweenness()tie_by_betweenness() erroring on signed networks, which reads each tie by its magnitude so that every tie keeps a value (closes #25)net_by_modularity() erroring on signed networks (closes #25)net_by_core() and net_by_factions() to stop with a clear message on a multilevel network, since a create_*() ideal covers one layer (closes #26)net_by_spatial() to name a non-numeric attribute (closes #26)limit= to net_by_strength() and net_by_toughness(), which take a minimum over 2^n subsets and so hang above about twenty nodes or ties (closes #34)fict_greys instead of fict_marvelnode_in_community() erroring on signed networks, which now considers only node_in_spinglass() (closes #25)node_in_core() and node_by_core() returning two values per node on multilevel networks (closes #26)coreness_rich() reading a multilevel network as a plain two-mode one (closes #26)cluster_cosine() to cluster nodes and not census features (thanks @Kaladani).onAttach() making library(netrics) faster to attachactions/actions/checkout path segmentparam_cutoffparam_decayparam_timesparam_variantparam_standardizedparam_connectivityNEWS.md family headings{migraph}make_*_measure() to record algorithm details so results can be read without the script/manual
measure actually calculated, e.g. node_by_degree() is "strength centrality" on a weighted networknormalization, one of "normalized", "scaled", "proportional" or "none"range, the theoretical range of the returned valuesvariant computed where a measure offers a choice, e.g. net_by_reciprocity() reports "ratio" when asked{manynet}, which defaults to previous behaviormeasure, range, normalization, and variant reporting to every measure where applicablenode_by_betweenness(cutoff = k) is distance-bounded or range-limited betweennessnode_by_reach(cutoff = k) is geodesic k-path centralitynode_by_closeness() as the Sabidussi indexnode_by_degree() on a weighted network as strength or weighted degree centralitynode_by_alpha() as Katz statusnode_by_hub() and node_by_authority() as the two halves of Kleinberg's HITSnode_by_transitivity() as the local clustering coefficienttie_by_betweenness() as edge betweennessnode_by_subgraph() as a node's contribution to the Estrada indexnode_by_induced() and node_by_vitality() as delta centralitynode_by_information() as the closeness member of the current-flow familynode_by_induced() also calling itself "vitality centrality"scale argument to scaled; old spelling still works but warnsdecay
alpha in node_by_alpha(), beta in regularity_rolesim()
alpha now only refers to Opsahl et al.'s trade-off between degree and strength in node_by_degree()decay argument to node_by_harmonic(), and node_by_decay() as a shortcut for decay centralitydecay to node_by_pagerank(), exposing the damping factor previously fixed at 0.85decay to node_by_subgraph(), weighting closed walks by length, which Estrada calls tscale doesnode_by_degree() to default to alpha = 0 to match documentationmode_by_betweenness() to accept only "all" and "in", as implementednode_by_reach() counting the node itself so normalised scores could exceed 1node_by_eigenvector() discarding tie weights it had computedtie_by_betweenness() and node_by_randomwalk() accepting normalized and then ignoring itnode_by_betweenness() accepting normalized and then ignoring it when given a cutoffnode_by_vitality() treats cut nodes
-Inf for cut nodes as the Wiener index definition requires[0,1] and places cut nodes at 0net_by_efficiency() to implement Krackhardt's share of excess ties
net_x_hierarchy() now compares four quantities already on [0,1]net_by_immunity() returning a negative herd immunity threshold when \eqn{R < 1}net_by_density(), net_by_equivalency() and node_by_reciprocity() summing tie weightsnode_by_closeness() to validate direction via match.arg()direction from net_by_betweenness() which never used itnode_by_posneg() to the eigenvector doc groupnode_by_subgraph()
walks= to choose which closed walks to count: "odd", "even" or "all"node_by_eigenvector() to cite Bonacich (1972), not only (1991)node_by_degree() and the centralisation functionsnet_by_bipartivity() for how close a network is to being bipartitenet_by_cyclicality() for detecting generalised exchangenet_by_compactness() for the average closeness of all pairs of nodesnode_by_integration() and net_by_integration() for Valente and Foreman's integration and radialitynode_by_radiality() as a shortcut for node_by_integration(direction = "out")net_by_inconsistency() for how far a partition's blocks depart from ideal types
nul, com, reg, rdo, cdo and dncnet_by_factions() beyond structural equivalencenode_by_equivalency() erroring on any network, despite being documented for the two-mode casenode_by_diversity() reporting undefined objects when substituting an inapplicable indexnet_by_transmissibility() declaring itself a proportionnet_by_balance() erroring on networks holding signs as negative weightsnet_by_diameter(), net_by_length() and net_by_compactness() on signed networks
node_by_reciprocity() to return 1 throughout for any undirected networknode_by_information() on rectangular matrices by using manynet::to_multilevel()net_by_independence() erroring on multilevel networks by measuring wholenet_by_waves() reporting one wave where waves are held as timeconnectivity= to net_by_components() for counting weak as well as strong components
"strong", so existing scripts are unaffectedvariant when the result is printedk= to community detection functions to target a specific number of communities (thanks @tomasdiviak)
knode_in_louvain() and node_in_leiden() search the resolution parameter for the value that returns knode_in_fluid() passes k straight to the algorithm, which also makes it much fasternode_in_labels() seeds k fixed labels and merges any surplus groups by modularitynode_in_partition() is now a k-way Kernighan-Lin, and no longer returns only two groupsnode_in_community() considers only these algorithms when k is givenk also accepts "silhouette", "elbow", and "strict", as in node_in_equivalence()k= is now positioned second, so positional calls must name argumentsnode_in_fluid() and node_in_spinglass() aborting silently on disconnected networksnode_in_labels() for label propagation community detectiontimes= in node_in_walktrap() to steps=consensus= to node_in_community() for combining partitions of all applicable algorithms
times), then converges on common groupingsconsensus = FALSE default, and ignored where network small enough for node_in_optimal()"verbose"node_by_coreness() to node_by_core()
node_in_core()
centrality= to coreness=
"rich" by default for weighted, directed or two-mode networks"correlation" otherwisedirection= for directed networks
"Sender" for core out-ties and periphery in-ties"Receiver" for core in-ties and periphery out-tiesnode_in_equivalence() to announce the cluster_*() and k_*() usednode_in_block() for direct blockmodelling for partitions that minimise net_by_inconsistency()node_in_regular() to compute regular equivalence correctly
regularity = "rolesim" (default) and "rege" for recursive similaritynode_in_regular() will now return more correct resultsnode_in_motif(),
though neither is Burt's equivalence or an orbit-aware census (thanks @Kaladani)Kmax= to max_k= in the community and equivalence functionsnum_groups= to groups= in node_in_roulette()cluster_by= to split= in node_in_core()connectivity= to node_in_component() for weak as well as strong component membership
"strong", so existing scripts are unaffectednode_in_weak() and node_in_strong()net_x_triad()
net_x_mixed()net_x_mixed()node_x_clique(), returning which maximal cliques each node belongs to
node_x_tie()
node_in_equivalence() and node_in_structural()type tie attributenode_x_ties(), describing the distribution of each node's tie values
node_x_alters() for describing composition of each node's altersnode_x_similarity() for describing similarity of each node to its alters
net_x_homophily() for the table behind the EI index against expected baselineregularity_rolesim() and regularity_rege(), recursive role similarity methods
regularity_rege() is degenerate on unweighted connected networks, where it warnscoreness_correlation() is Borgatti and Everett's continuous model, fixed to exclude self-tiescoreness_rich() is Ma and Mondragon's rich-core for directed and two-mode networkscoreness_hub() is Elliott and colleagues' more granualr directed core-peripherycoreness_transition() is Rombach and colleagues' core score over boundary sharpness and core sizesplit_bins(), split_quantiles() and split_kmeans()
node_in_regular() for regular equivalence rather than the triad censusConfig/Needs/check packages instead of Config/Needs/website, which meant {learnr} was never actually installed before the pkgdown deploy stepequivalency, partition, faction) in the community tutorial that had no matching {manynet} glossary entry, which was breaking the tutorial's article renderingnode_x_brokerage() and net_x_brokerage()) to the position tutorialnet_by_degree(), net_by_indegree(), net_by_outdegree(), net_by_betweenness(), net_by_closeness(), and net_by_eigenvector() now return a single network-level score for two-mode networks (via Freeman's general centralization index over the mode-normalized node scores), consistent with returning a scalar network_measure for all networks
mode_by_*() family (mode_by_degree(), mode_by_indegree(), mode_by_outdegree(), mode_by_betweenness(), mode_by_closeness(), mode_by_eigenvector()) that returns the per-mode centralization scores for two-mode networks, following Borgatti and Everett (1997); these error on one-mode networksnet_by_betweenness() to respect its normalized argument for one-mode networks, which was previously ignored because igraph::centr_betw() always applied its default normalizationnet_by_closeness() and mode_by_closeness() to pass their direction argument through to the underlying node scores, so direction = "in"/"all" is now effective for two-mode networksnetrics1) with a new interactive style, and added an article version to the website
netrics2) with a new versionnetrics3) with a new interactive style
netrics4) with a new interactive style
node_by_homophily() to work when attribute is provided as a vector (e.g., a membership vector)node_by_homophily() to avoid calling as_igraph() multiple timesnet_x_hazard() to use diff_model$t for naming the returned data frame columns, rather than the deprecated diff_model$time{manynet}node_in_partition()param_attr, param_data,
param_dir, param_memb, param_motf, param_norm, param_select) and
net/node/tie-level templates (net_measure, net_motif, node_mark,
node_measure, node_member, node_motif, tie_mark, tie_measure) for
consistent function documentation.node_adoption_time() to node_by_adopt_time()node_thresholds() to node_by_adopt_threshold()node_exposure() to node_by_adopt_exposure()node_recovery() to node_by_adopt_recovery()node_in_community() documentation from the hierarchical
and non-hierarchical community-detection algorithms.net_by_change() to net_x_change() and related functions to
reflect their motif (subgraph-counting) nature.method_k().model_k() to method_k() and related cluster-selection utilities
renamed for clarity.{netrics} 0.1.0 is the first formal release of the package as a standalone
analytic engine for the stocnet ecosystem.
The analytic functions — marks, measures, motifs, and memberships — have been
extracted from {manynet} and {migraph} into this dedicated package, with
consistent naming conventions and a range of bug fixes.
All functions now follow a consistent verb–object–qualifier naming scheme:
node_is_*(), tie_is_*()): logical vectors identifying which nodes
or ties hold a particular structural property.*_by_*()): numeric vectors at the network (net_by_*()),
node (node_by_*()), or tie (tie_by_*()) level.*_x_*()): tabular counts of nodes' or networks' participation
in structural sub-patterns.*_in_*()): categorical vectors assigning nodes to groups
(components, communities, equivalence classes, etc.).Functions previously named with other prefixes (e.g. node_centrality_*,
net_cohesion_*, node_equivalency_*) have been renamed to follow the
*_by_*() / *_x_*() / *_in_*() convention.
tie_by_cohesion() now correctly returns a tie_measure class object.
The following groups of functions have been moved into {netrics}:
node_is_core(), node_is_cutpoint(), node_is_exposed(),
node_is_fold(), node_is_independent(), node_is_infected(),
node_is_isolate(), node_is_latent(), node_is_max(),
node_is_mean(), node_is_mentor(), node_is_min(),
node_is_neighbor(), node_is_pendant(), node_is_random(),
node_is_recovered(), node_is_universal()tie_is_bridge(), tie_is_cyclical(), tie_is_feedback(),
tie_is_imbalanced(), tie_is_loop(), tie_is_max(),
tie_is_min(), tie_is_multiple(), tie_is_path(),
tie_is_random(), tie_is_reciprocated(), tie_is_simmelian(),
tie_is_transitive(), tie_is_triangular(), tie_is_triplet()net_by_adhesion(), net_by_assortativity(),
net_by_balance(), net_by_betweenness(), net_by_change(),
net_by_closeness(), net_by_cohesion(), net_by_components(),
net_by_congruency(), net_by_connectedness(), net_by_core(),
net_by_correlation(), net_by_degree(), net_by_density(),
net_by_diameter(), net_by_diversity(), net_by_efficiency(),
net_by_eigenvector(), net_by_equivalency(), net_by_factions(),
net_by_harmonic(), net_by_heterophily(), net_by_hierarchy(),
net_by_homophily(), net_by_immunity(), net_by_indegree(),
net_by_independence(), net_by_infection_complete(),
net_by_infection_peak(), net_by_infection_total(),
net_by_length(), net_by_modularity(), net_by_outdegree(),
net_by_reach(), net_by_reciprocity(), net_by_recovery(),
net_by_reproduction(), net_by_richclub(), net_by_richness(),
net_by_scalefree(), net_by_smallworld(), net_by_spatial(),
net_by_stability(), net_by_strength(), net_by_toughness(),
net_by_transitivity(), net_by_transmissibility(),
net_by_upperbound(), net_by_waves()node_by_adoption_time(), node_by_alpha(),
node_by_authority(), node_by_betweenness(), node_by_bridges(),
node_by_brokering_activity(), node_by_brokering_exclusivity(),
node_by_closeness(), node_by_constraint(), node_by_coreness(),
node_by_deg(), node_by_degree(), node_by_distance(),
node_by_diversity(), node_by_eccentricity(),
node_by_efficiency(), node_by_effsize(), node_by_eigenvector(),
node_by_equivalency(), node_by_exposure(), node_by_flow(),
node_by_harmonic(), node_by_heterophily(), node_by_hierarchy(),
node_by_homophily(), node_by_hub(), node_by_indegree(),
node_by_induced(), node_by_information(), node_by_kcoreness(),
node_by_leverage(), node_by_multidegree(),
node_by_neighbours_degree(), node_by_outdegree(),
node_by_pagerank(), node_by_posneg(), node_by_power(),
node_by_randomwalk(), node_by_reach(), node_by_reciprocity(),
node_by_recovery(), node_by_redundancy(), node_by_richness(),
node_by_stress(), node_by_subgraph(), node_by_thresholds(),
node_by_transitivity(), node_by_vitality()tie_by_betweenness(), tie_by_closeness(),
tie_by_cohesion(), tie_by_degree(), tie_by_eigenvector()net_x_brokerage(), net_x_dyad(), net_x_hazard(),
net_x_mixed(), net_x_tetrad(), net_x_triad()node_x_brokerage(), node_x_dyad(), node_x_exposure(),
node_x_path(), node_x_tetrad(), node_x_tie(), node_x_triad()node_in_adopter(), node_in_automorphic(),
node_in_betweenness(), node_in_brokering(),
node_in_community(), node_in_component(), node_in_core(),
node_in_eigen(), node_in_equivalence(), node_in_fluid(),
node_in_greedy(), node_in_infomap(), node_in_leiden(),
node_in_louvain(), node_in_optimal(), node_in_partition(),
node_in_regular(), node_in_roulette(), node_in_spinglass(),
node_in_strong(), node_in_structural(), node_in_walktrap(),
node_in_weak()node_is_isolate() and node_is_pendant() now work correctly with signed networks.tie_is_random() now correctly returns a tie_mark class object (previously returned a node mark).node_by_authority() and node_by_hub() updated to use current {igraph} API.node_by_brokering_activity() and node_by_brokering_exclusivity() now handle unlabelled networks correctly.node_by_homophily() no longer resolves the attribute to a vector prematurely.node_by_pagerank() updated to correctly extract the vector output from {igraph}.node_by_power() reverts to a lower exponent (closer to degree centrality) when there is no degree variation.node_by_randomwalk() now works with two-mode networks.net_by_degree(), net_by_harmonic(), and net_by_reach() now consistently include the function call in the returned object.net_by_richclub() returns 0 (rather than erroring) when all nodes have equivalent degree.net_by_smallworld() and node_by_bridges() now use internal {netrics} functions rather than {manynet} equivalents.net_by_waves() returns 1 for cross-sectional networks and correctly returns a network measure class.net_x_hierarchy() correctly classified as a motif function.node_in_community() now delegates to {netrics} membership functions internally.tie_by_cohesion() now correctly returns a tie_measure class object.