#' Merge communities from graph-based clustering
#'
#' Adjust the resolution of a graph-based community detection algorithm by greedily merging clusters together.
#' At each step, the pair of clusters that yield the highest modularity are merged.
#'
#' @inheritParams pairwiseModularity
#' @param number Integer scalar specifying the number of clusters to obtain.
#' Ignored if \code{steps} is specified.
#' @param steps Integer scalar specifying the number of merge steps.
#'
#' @return A vector or factor of the same length as \code{clusters},
#' containing the desired number of merged clusters.
#'
#' @details
#' This function is similar to the \code{\link{cut_at}} function from the \pkg{igraph} package,
#' but works on clusters that were not generated by a hierarchical algorithm.
#' The aim is to facilitate rapid adjustment of the number of clusters without having to repeat the clustering -
#' or, even worse, repeating the graph construction, e.g., in \code{\link{makeSNNGraph}}.
#'
#' @author Aaron Lun
#'
#' @examples
#' output <- clusterRows(iris[,1:4], NNGraphParam(k=5), full=TRUE)
#' table(output$clusters)
#'
#' merged <- mergeCommunities(output$objects$graph, output$clusters, number=3)
#' table(merged)
#'
#' @seealso
#' \code{\link{cut_at}}, for a faster and more natural adjustment when using a hierarchical community detection algorithm.
#'
#' \linkS4class{NNGraphParam}, for a one-liner to generate graph-based clusters.
#' @export
#' @importFrom igraph modularity E
mergeCommunities <- function(graph, clusters, number=NULL, steps=NULL) {
nclusters <- length(unique(clusters))
if (is.null(steps)) {
if (is.null(number)) {
stop("either 'number' or 'steps' must be specified")
}
steps <- max(0, nclusters - number)
}
if (steps >= nclusters) {
clusters <- rep(clusters[1], length(clusters))
} else if (steps > 0) {
for (i in seq_len(steps)) {
labels <- unique(clusters)
max.m <- 0
max.label <- clusters
# Picking the pair to merge that yields the greatest modularity.
for (lab in labels) {
to.merge <- clusters==lab
for (other in labels) {
if (other==lab) {
next
}
next.label <- clusters
next.label[to.merge] <- other
next.m <- modularity(graph, next.label, weights=E(graph)$weight)
if (max.m < next.m) {
max.m <- next.m
max.label <- next.label
}
}
}
clusters <- max.label
}
}
if (is.factor(clusters)) {
droplevels(clusters)
} else {
clusters
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.