Nothing
#' Querying node types
#'
#' These functions all lets the user query whether each node is of a certain
#' type. All of the functions returns a logical vector indicating whether the
#' node is of the type in question. Do note that the types are not mutually
#' exclusive and that nodes can thus be of multiple types.
#'
#' @param mode The way edges should be followed in the case of directed graphs.
#'
#' @return A logical vector of the same length as the number of nodes in the
#' graph.
#'
#' @name node_types
#' @rdname node_types
#'
#' @examples
#' # Find the root and leafs in a tree
#' create_tree(40, 2) %>%
#' mutate(root = node_is_root(), leaf = node_is_leaf())
NULL
#' @describeIn node_types is the node a cut node (articaultion node)
#' @importFrom igraph gorder articulation_points
#' @export
node_is_cut <- function() {
expect_nodes()
graph <- .G()
focus_ind(graph, 'nodes') %in% articulation_points(graph)
}
#' @describeIn node_types is the node a root in a tree
#' @importFrom igraph degree is_directed
#' @export
node_is_root <- function() {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
if ((!is_tree(graph) && !is_forest(graph)) || !is_directed(graph)) {
return(rep(FALSE, length(node_inds)))
}
deg_in <- degree(graph, mode = 'in') == 0
deg_out <- degree(graph, mode = 'out') == 0
root <- if (sum(deg_in) > sum(deg_out)) deg_out else deg_in
root[node_inds]
}
#' @describeIn node_types is the node a leaf in a tree
#' @importFrom igraph degree is_directed
#' @export
node_is_leaf <- function() {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
if ((!is_tree(graph) && !is_forest(graph))) {
return(rep(FALSE, length(node_inds)))
}
if (is_directed(graph)) {
deg_in <- degree(graph, mode = 'in') == 0
deg_out <- degree(graph, mode = 'out') == 0
leaf <- if (sum(deg_out) > sum(deg_in)) deg_out else deg_in
leaf[node_inds]
} else {
degree(graph, v = node_inds, mode = 'all') == 1
}
}
#' @describeIn node_types does the node only have incomming edges
#' @importFrom igraph degree
#' @export
node_is_sink <- function() {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
deg_in <- degree(graph, v = node_inds, mode = 'in')
deg_out <- degree(graph, v = node_inds, mode = 'out')
deg_out == 0 & deg_in != 0
}
#' @describeIn node_types does the node only have outgoing edges
#' @importFrom igraph degree
#' @export
node_is_source <- function() {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
deg_in <- degree(graph, v = node_inds, mode = 'in')
deg_out <- degree(graph, v = node_inds, mode = 'out')
deg_out != 0 & deg_in == 0
}
#' @describeIn node_types is the node unconnected
#' @importFrom igraph degree
#' @export
node_is_isolated <- function() {
expect_nodes()
graph <- .G()
degree(graph, v = focus_ind(graph, 'nodes')) == 0
}
#' @describeIn node_types is the node connected to all other nodes in the graph
#' @importFrom igraph ego_size gorder
#' @export
node_is_universal <- function(mode = 'out') {
expect_nodes()
graph <- .G()
ego_size(graph, order = 1, nodes = focus_ind(graph, 'nodes'), mode = mode) == gorder(graph)
}
#' @describeIn node_types are all the neighbors of the node connected
#' @importFrom igraph local_scan ecount ego_size
#' @export
node_is_simplical <- function(mode = 'out') {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
n_edges <- local_scan(graph, k = 1, mode = mode, FUN = ecount)[node_inds]
n_nodes <- ego_size(graph, order = 1, nodes = node_inds, mode = mode)
n_edges == n_nodes * (n_nodes - 1) * 0.5
}
#' @describeIn node_types does the node have the minimal eccentricity in the graph
#' @importFrom igraph eccentricity
#' @export
node_is_center <- function(mode = 'out') {
expect_nodes()
graph <- .G()
ecc <- eccentricity(graph, mode = mode)
ecc[focus_ind(graph, 'nodes')] == min(ecc)
}
#' @describeIn node_types is a node adjacent to any of the nodes given in `to`
#' @param to The nodes to test for adjacency to
#' @param include_to Should the nodes in `to` be marked as adjacent as well
#' @importFrom igraph adjacent_vertices
#' @export
node_is_adjacent <- function(to, mode = 'all', include_to = TRUE) {
expect_nodes()
graph <- .G()
to <- as_node_ind(to, graph)
include <- unlist(adjacent_vertices(graph, to, mode))
if (include_to) include <- union(to, include)
focus_ind(graph, 'nodes') %in% include
}
#' @describeIn node_types Is a node part of the keyplayers in the graph (`influenceR`)
#' @param k The number of keyplayers to identify
#' @param p The probability to accept a lesser state
#' @param tol Optimisation tolerance, below which the optimisation will stop
#' @param maxsec The total computation budget for the optimization, in seconds
#' @param roundsec Number of seconds in between synchronizing workers' answer
#' @importFrom igraph gorder
#' @export
node_is_keyplayer <- function(k, p = 0, tol = 1e-4, maxsec = 120, roundsec = 30) {
expect_influencer()
expect_nodes()
graph <- .G()
ind <- influenceR::keyplayer(graph, k = k, prob = p, tol = tol, maxsec = maxsec, roundsec = roundsec)
focus_ind(graph, 'nodes') %in% ind
}
#' @describeIn node_types Is a node connected to all (or any) nodes in a set
#' @param nodes The set of nodes to test connectivity to. Can be a list to use
#' different sets for different nodes. If a list it will be recycled as
#' necessary.
#' @param any Logical. If `TRUE` the node only needs to be connected to a single
#' node in the set for it to return `TRUE`
#' @importFrom igraph distances gorder
#' @export
node_is_connected <- function(nodes, mode = 'all', any = FALSE) {
expect_nodes()
graph <- .G()
node_inds <- focus_ind(graph, 'nodes')
if (!is.list(nodes)) nodes <- list(nodes)
all_nodes <- unique(unlist(nodes))
reached <- is.finite(t(distances(graph, v = node_inds, to = all_nodes, mode = mode, weights = NA)))
nodes <- rep_len(nodes, length(node_inds))
vapply(seq_along(node_inds), function(i) {
n <- node_inds[i]
connections <- match(nodes[[i]], all_nodes)
found <- reached[,n][connections]
if (any) any(found) else all(found)
}, logical(1))
}
#' Querying node measures
#'
#' These functions are a collection of node measures that do not really fall
#' into the class of [centrality] measures. For lack of a better place they are
#' collected under the `node_*` umbrella of functions.
#'
#' @param mode How edges are treated. In `node_coreness()` it chooses which kind
#' of coreness measure to calculate. In `node_efficiency()` it defines how the
#' local neighborhood is created
#' @param weights The weights to use for each node during calculation
#' @param directed Should the graph be treated as a directed graph if it is in
#' fact directed
#'
#' @return A numeric vector of the same length as the number of nodes in the
#' graph.
#'
#' @name node_measures
#' @rdname node_measures
#'
#' @examples
#' # Calculate Burt's Constraint for each node
#' create_notable('meredith') %>%
#' mutate(b_constraint = node_constraint())
NULL
#' @describeIn node_measures measure the maximum shortest path to all other nodes in the graph
#' @importFrom igraph eccentricity
#' @export
node_eccentricity <- function(mode = 'out') {
expect_nodes()
graph <- .G()
eccentricity(graph, focus_ind(graph, 'nodes'), mode = mode)
}
#' @describeIn node_measures measures Burts constraint of the node. See [igraph::constraint()]
#' @importFrom igraph constraint
#' @export
node_constraint <- function(weights = NULL) {
expect_nodes()
graph <- .G()
weights <- enquo(weights)
weights <- eval_tidy(weights, .E())
if (is.null(weights)) {
weights <- rep_len(1L, gsize(graph))
}
constraint(graph, focus_ind(graph, 'nodes'), weights = weights)
}
#' @describeIn node_measures measures the coreness of each node. See [igraph::coreness()]
#' @importFrom igraph coreness
#' @export
node_coreness <- function(mode = 'out') {
expect_nodes()
graph <- .G()
coreness(graph, mode = mode)[focus_ind(graph, 'nodes')]
}
#' @describeIn node_measures measures the diversity of the node. See [igraph::diversity()]
#' @importFrom igraph diversity
#' @export
node_diversity <- function(weights) {
expect_nodes()
graph <- .G()
if (missing(weights)) {
cli::cli_abort('{.arg weights} must be provided')
}
weights <- enquo(weights)
weights <- eval_tidy(weights, .E())
if (is.null(weights)) {
cli::cli_abort('{.arg weights} must be a valid vector')
}
diversity(graph, weights = weights, vids = focus_ind(graph, 'nodes'))
}
#' @describeIn node_measures measures the local efficiency around each node. See [igraph::local_efficiency()]
#' @importFrom rlang enquo eval_tidy
#' @importFrom igraph local_efficiency
#' @export
node_efficiency <- function(weights = NULL, directed = TRUE, mode = 'all') {
expect_nodes()
graph <- .G()
weights <- enquo(weights)
weights <- eval_tidy(weights, .E()) %||% NA
local_efficiency(graph, focus_ind(graph, 'nodes'), weights, directed, mode)
}
#' @describeIn node_measures measures Valente's Bridging measures for detecting structural bridges (`influenceR`)
#' @export
node_bridging_score <- function() {
expect_influencer()
expect_nodes()
graph <- .G()
influenceR::bridging(graph)[focus_ind(graph, 'nodes')]
}
#' @describeIn node_measures measures Burt's Effective Network Size indicating access to structural holes in the network (`influenceR`)
#' @export
node_effective_network_size <- function() {
expect_influencer()
expect_nodes()
graph <- .G()
influenceR::ens(graph)[focus_ind(graph, 'nodes')]
}
#' @describeIn node_measures measures the impact on connectivity when removing the node (`NetSwan`)
#' @export
node_connectivity_impact <- function() {
expect_netswan()
expect_nodes()
graph <- .G()
NetSwan::swan_connectivity(graph)[focus_ind(graph, 'nodes')]
}
#' @describeIn node_measures measures the impact on closeness when removing the node (`NetSwan`)
#' @export
node_closeness_impact <- function() {
expect_netswan()
expect_nodes()
graph <- .G()
NetSwan::swan_closeness(graph)[focus_ind(graph, 'nodes')]
}
#' @describeIn node_measures measures the impact on fareness (distance between all node pairs) when removing the node (`NetSwan`)
#' @export
node_fareness_impact <- function() {
expect_netswan()
expect_nodes()
graph <- .G()
NetSwan::swan_efficiency(graph)[focus_ind(graph, 'nodes')]
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.