| cluster_summary | R Documentation |
Aggregates node-level network weights to cluster-level summaries. Computes both between-cluster transitions (how clusters connect to each other) and within-cluster transitions (how nodes connect within each cluster).
cluster_summary(
x,
clusters = NULL,
method = c("sum", "mean", "median", "max", "min", "density", "geomean"),
directed = TRUE,
compute_within = TRUE
)
x |
Network input. Accepts multiple formats:
|
clusters |
Cluster/group assignments for nodes. Accepts multiple formats:
|
method |
Aggregation method for combining edge weights within/between clusters. Controls how multiple node-to-node edges are summarized:
|
directed |
Logical. If |
compute_within |
Logical. If |
This is the core function for Multi-Cluster Multi-Level (MCML) analysis.
Use as_tna() to convert results to tna objects for further
analysis with the tna package.
Typical MCML analysis workflow:
# 1. Create network net <- build_network(data, method = "relative") net$nodes$clusters <- group_assignments # 2. Compute cluster summary (arithmetic aggregation over edges) cs <- cluster_summary(net, method = "sum") # 3. Convert to tna models (normalization happens in as_tna) tna_models <- as_tna(cs) # 4. Analyze/visualize plot(tna_models$macro) tna::centralities(tna_models$macro)
The macro$weights matrix has clusters as both rows and columns:
Off-diagonal (row i, col j): Aggregated weight from cluster i to cluster j
Diagonal (row i, col i): Within-cluster total (aggregation of internal edges)
Rows are NOT normalized. Entries are elementwise aggregates produced by
method. If the caller wants probabilities, they should normalize
downstream (e.g. via as_tna()). Mixing an arithmetic aggregation
with row-normalization here (the old type = "tna" combined with
method = "min" / "mean" etc.) produces numbers that sum to 1
per row but are not a probability distribution over any process; that
silently-wrong combination is why type was removed from the matrix
path. The sequence and edgelist paths of build_mcml() keep
type, where the aggregation is always counts and the post-processing
chooses between well-defined network constructions.
| Input data | Recommended method | Reason |
| Edge counts | "sum" | Preserves total flow between clusters |
| Transition matrix | "mean" | Avoids cluster size bias |
| Correlation matrix | "mean" | Average correlations |
| Dense weighted | "max" / "median" | Robust summary |
A cluster_summary object (S3 class) containing:
List with two elements:
k x k matrix of cluster-to-cluster weights, where k is
the number of clusters. Row i, column j contains the elementwise
aggregation (per method) of all edges from nodes in cluster
i to nodes in cluster j. Diagonal contains within-cluster totals.
Pure arithmetic – no row normalization.
Numeric vector of length k. Initial state distribution across clusters, computed from column sums of the original matrix. Represents the proportion of incoming edges to each cluster.
Named list with one element per cluster. Each element contains:
n_i x n_i matrix for nodes within that cluster. Shows internal transitions between nodes in the same cluster.
Initial distribution within the cluster.
NULL if compute_within = FALSE.
Named list mapping cluster names to their member node labels.
Example: list(A = c("n1", "n2"), B = c("n3", "n4", "n5"))
List of metadata:
The method argument used ("sum", "mean", etc.)
Logical, whether network was treated as directed
Total number of nodes in original network
Number of clusters
Named vector of cluster sizes
as_tna() to convert results to tna objects,
plot() for two-layer visualization,
plot() for flat cluster visualization
# -----------------------------------------------------
# Basic usage with matrix and cluster vector
# -----------------------------------------------------
mat <- matrix(runif(100), 10, 10)
rownames(mat) <- colnames(mat) <- LETTERS[1:10]
clusters <- c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3)
cs <- cluster_summary(mat, clusters)
# Access results
cs$macro$weights # 3x3 cluster transition matrix
cs$macro$inits # Initial distribution
cs$clusters$`1`$weights # Within-cluster 1 transitions
cs$meta # Metadata
# -----------------------------------------------------
# Named list clusters (more readable)
# -----------------------------------------------------
clusters <- list(
Alpha = c("A", "B", "C"),
Beta = c("D", "E", "F"),
Gamma = c("G", "H", "I", "J")
)
cs <- cluster_summary(mat, clusters)
cs$macro$weights # Rows/cols named Alpha, Beta, Gamma
cs$clusters$Alpha # Within Alpha cluster
# -----------------------------------------------------
# Auto-detect clusters from netobject
# -----------------------------------------------------
seqs <- data.frame(
V1 = sample(LETTERS[1:10], 30, TRUE), V2 = sample(LETTERS[1:10], 30, TRUE),
V3 = sample(LETTERS[1:10], 30, TRUE)
)
net <- build_network(seqs, method = "relative")
cs2 <- cluster_summary(net, c(1, 1, 1, 2, 2, 2, 3, 3, 3, 3))
# -----------------------------------------------------
# Different aggregation methods
# -----------------------------------------------------
cs_sum <- cluster_summary(mat, clusters, method = "sum") # Total flow
cs_mean <- cluster_summary(mat, clusters, method = "mean") # Average
cs_max <- cluster_summary(mat, clusters, method = "max") # Strongest
# -----------------------------------------------------
# Skip within-cluster computation for speed
# -----------------------------------------------------
cs_fast <- cluster_summary(mat, clusters, compute_within = FALSE)
cs_fast$clusters # NULL
# -----------------------------------------------------
# Convert to tna objects for tna package
# (as_tna() applies its own row normalisation)
# -----------------------------------------------------
cs <- cluster_summary(mat, clusters, method = "sum")
tna_models <- as_tna(cs)
# tna_models$macro # tna object
# tna_models$clusters$Alpha # tna object
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.