infomap

R bindings for the Infomap network clustering algorithm. Infomap decomposes a network into modules by optimally compressing a description of information flows on the network using the Map Equation.

Installation

Pre-built binaries (no compiler required) — the recommended path:

install.packages(
  "infomap",
  repos = c("https://mapequation.r-universe.dev", "https://cloud.r-project.org")
)

Source install from a release tarball — pick the version from the GitHub releases page:

# Replace VERSION with the desired tag, e.g. "2.13.0".
install.packages(
  paste0("https://github.com/mapequation/infomap/releases/download/v",
         "VERSION", "/infomap_", "VERSION", ".tar.gz"),
  repos = NULL
)

Source install from a git checkout (requires Python 3 and a C++17 compiler):

remotes::install_github("mapequation/infomap", subdir = "interfaces/R/infomap")

Quick start

library(infomap)

edges <- data.frame(
  source = c(1, 1, 2, 3, 4, 4, 5),
  target = c(2, 3, 3, 4, 5, 6, 6)
)

result <- cluster_infomap(edges, silent = TRUE, num_trials = 10)

result$codelength
result$num_top_modules
result$modules              # named integer vector: node_id -> module_id
result$nodes                # one row per node, with flow / name / module_id

If igraph is also attached, use infomap::cluster_infomap() or igraph::cluster_infomap() to choose explicitly. infomap returns an infomap_result; use as_communities(result, graph) when you need an igraph communities object.

For more control, use the low-level R6 API directly:

im <- Infomap(silent = TRUE, num_trials = 10)
im$add_links(list(c(1, 2), c(1, 3), c(2, 3),
                  c(3, 4),
                  c(4, 5), c(4, 6), c(5, 6)))
im$run()

im$codelength
im$num_top_modules
im$modules                # named integer vector: node_id -> module_id
as.data.frame(im)         # one row per node, with path / flow / name / module_id

See ?cluster_infomap for the one-call helper, ?Infomap for the low-level constructor plus the InfomapClass method and active-binding reference, and ?infomap_options for the complete list of named options.

Multilayer networks

Cluster a multilayer network with cluster_infomap_multilayer(). Pass a data frame of intra-layer links (layer, node_from, node_to) and let Infomap couple layers automatically via multilayer_relax_rate, or pass full multilayer links (layer_from, node_from, layer_to, node_to, optional weight) to set inter-layer couplings explicitly:

intra <- data.frame(
  layer     = c(1, 1, 1, 2, 2, 2),
  node_from = c(1, 2, 3, 1, 2, 3),
  node_to   = c(2, 3, 1, 2, 3, 1)
)

result <- cluster_infomap_multilayer(intra, silent = TRUE, num_trials = 10)
result$codelength
result$nodes        # one row per state node, including a `layer_id` column

For weighted inter-layer couplings that come from a different source than the intra-layer links, use the low-level R6 API with im$add_multilayer_intra_link() and im$add_multilayer_inter_link(). See ?cluster_infomap_multilayer and examples/R/example-multilayer.R for a full walkthrough.

Working with igraph

igraph is a Suggests dependency, not a hard requirement — install it separately if you want to import existing graphs:

install.packages("igraph")

library(igraph)
library(infomap)

g <- make_graph("Zachary")

im <- Infomap(silent = TRUE, two_level = TRUE)
mapping <- im$add_igraph(g)   # invisibly returns id -> vertex name
im$run()

comm <- im$as_communities(g)  # igraph 'communities' object

add_igraph() and as_communities() raise an informative error if igraph is not installed.

add_igraph() uses an igraph edge attribute named weight by default. Use weight = NULL to use that attribute only when present, or weight = FALSE to ignore edge weights. Non-numeric or missing weight values raise an error.

Node id convention. Infomap result accessors report the numeric node ids used to build the network. For links added directly with add_link() or add_links(), Infomap preserves those user-supplied ids. add_igraph() uses R igraph's 1-indexed vertex ids as state ids. Plain graph results use those ids directly. State and multilayer graphs can use separate physical ids from a node_id vertex attribute; the package maps non-numeric physical labels to stable internal integers. The mapping returned by add_igraph() recovers the original igraph vertex names (or stringified vertex ids) keyed by vertex id. When the package mapped labels this way, attr(mapping, "node_id") maps the internal physical ids back to the original physical labels.

Related packages

infomap is also distributed as a Python package on PyPI and an npm package as @mapequation/infomap. The C++ core, SWIG interface, and documentation live in the Infomap repository.