R network analysis with igraph fronted by tidygraph + ggraph: graph construction from edge-list tibbles (tidyverse round-trip), centrality (degree, betweenness, closeness, eigenvector, PageRank), community detection (Leiden, Louvain, walktrap) with seed discipline, shortest paths, components, bipartite construction + projection, and static grammar-of-graphics figures via ggraph with seeded layouts. Use for relational/graph data. For road-network routing use sf-terra (sfnetworks); for non-grap...
Installs into .claude/skills of the current project.
Are you the author of Igraph R?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/daaf-contribution-community-igraph-r)
---
name: igraph-r
description: >-
R network analysis with igraph fronted by tidygraph + ggraph: graph
construction from edge-list tibbles (tidyverse round-trip), centrality
(degree, betweenness, closeness, eigenvector, PageRank), community detection
(Leiden, Louvain, walktrap) with seed discipline, shortest paths, components,
bipartite construction + projection, and static grammar-of-graphics figures via
ggraph with seeded layouts. Use for relational/graph data. For road-network
routing use sf-terra (sfnetworks); for non-graph clustering use tidymodels.
Use when execution language is R. Python equivalent: igraph.
metadata:
audience: research-coders
domain: r-library
library-version: "igraph 2.2.3, tidygraph 1.3.1, ggraph 2.2.2"
skill-last-updated: "2026-07-15"
---
# igraph-r Skill
R network analysis with igraph (the C-core graph engine), fronted by tidygraph
(a tidy `tbl_graph` API that wraps igraph's full functionality with dplyr verbs)
and ggraph (grammar-of-graphics static network figures built on the tidygraph
data structure). Covers graph construction from edge-list tibbles with a
round-trip back to tidy node/edge tables, centrality (degree, betweenness,
closeness, eigenvector, PageRank), community detection (Leiden, Louvain,
walktrap) with mandatory seed discipline, shortest paths and connected
components, bipartite graph construction and one-mode projection, and static
visualization via ggraph with seeded layouts. Use when the execution language is
R and the task involves relational/network data. For road-network routing use
sf-terra (sfnetworks); for community detection framed as feature clustering
without an explicit graph, use tidymodels. ERGM/statnet inferential modeling is
deliberately out of scope (see Version Notes). Python equivalent: the igraph skill.
## What is igraph?
igraph is a single C library with R and Python bindings that run the same
algorithms — the R and Python skills share identical semantics because they wrap
the same core:
- **Graph objects**: An igraph object holds vertices and edges plus arbitrary
vertex/edge/graph attributes. Directedness is a graph-level property set at
construction (`directed = TRUE/FALSE`).
- **Attribute-driven**: Vertices and edges carry named attributes (`weight`,
`name`, `type`, etc.). Some attribute names are semantically special — most
importantly `weight`, which many functions consume automatically (see Gotchas).
- **Computational substrate**: igraph is the algorithmic engine. tidygraph and
ggraph front it for manipulation and plotting; raw igraph remains the escape
hatch for algorithms not surfaced tidily.
## What are tidygraph and ggraph?
tidygraph and ggraph give igraph a tidyverse face, matching DAAF's R house style:
- **tbl_graph**: tidygraph's `tbl_graph` is a graph whose node and edge tables are
manipulable with dplyr verbs. Any function that expects an igraph object also
accepts a `tbl_graph` — there is zero interop cost between the two.
- **activate()**: `activate(nodes)` / `activate(edges)` selects which table dplyr
verbs operate on. `as_tibble()` extracts the active table back to a plain tibble
for downstream statistics.
- **Grammar of graphics**: ggraph applies ggplot2 grammar to networks —
`ggraph(g, layout = ...) + geom_edge_link() + geom_node_point()`. Layouts are
a scale-like concept; force-directed layouts are stochastic and need a seed.
- **igraph underneath**: tidygraph re-exports centrality and community-detection
wrappers (`centrality_degree()`, `group_louvain()`, etc.), but they call the
same igraph routines and inherit the same gotchas (weight auto-use, seed
sensitivity). This skill shows both the raw igraph call and the tidygraph verb
where useful.
## Version Notes
Versions targeted in the DAAF container (R 4.5.3):
| Package | Version | Role | Status |
|---------|---------|------|--------|
| igraph | 2.2.3 | C-core graph engine | **Installed** (P3M snapshot 2026-04-15; CRAN latest is newer) |
| tidygraph | 1.3.1 | Tidy `tbl_graph` API over igraph | **Added to Dockerfile; NOT loadable until container rebuild** |
| ggraph | 2.2.2 | Grammar-of-graphics network figures | **Added to Dockerfile; NOT loadable until container rebuild** |
| graphlayouts | (P3M snapshot) | Layout algorithms; arrives as a ggraph dependency | **Added transitively with ggraph; exact snapshot version unresolved** |
**Installation state (read before running any tidygraph/ggraph code):**
- **igraph 2.2.3** is already installed — it was previously a transitive dependency
and is now promoted to a first-class framework package. Raw-igraph code runs today.
- **tidygraph 1.3.1** and **ggraph 2.2.2** were added to the Dockerfile's framework
R block but are **not loadable until the container is rebuilt**. Any script that
`library(tidygraph)` / `library(ggraph)` will error until then. To rebuild: exit
the container, then run `bash rebuild_daaf.sh` (`.\rebuild_daaf.ps1` on Windows)
from the `daaf-docker` folder.
- **graphlayouts** arrives as a ggraph dependency. At the P3M 2026-04-15 snapshot
it resolves to the release current on that date; the exact version is
**deliberately not pinned here** (the current CRAN 1.2.4 postdates the snapshot,
so the snapshot supplies an earlier release). Let the P3M snapshot resolve it at
build time rather than pinning a version that may not exist in the snapshot.
**igraph 2.x note:** The 2.0 release (May 2024) realigned R igraph to the 0.10 C
core, matching the Python side; the R and Python igraph skills therefore describe
the same algorithms with the same semantics.
**Out of scope — ERGM/statnet (deferred extension):** Exponential random graph
models (the `statnet` stack: `network`, `sna`, `ergm`) are a distinct inferential
method with MCMC cost, model-degeneracy hazards, and network-size limits. They are
**not covered by this skill** and belong to a separate, deferred advanced-inference
extension. This skill covers descriptive network analysis, community detection, and
visualization only.
## How to Use This Skill
### Reference File Structure
| File | Purpose | When to Read |
|------|---------|--------------|
| `quickstart.md` | tbl_graph construction, edge-list tibble ↔ graph round-trip, I/O, inspection | Starting out or a quick reminder |
| `centrality.md` | Degree, betweenness, closeness, eigenvector, PageRank; `weights = NA` discipline; component/mode guardrails | Computing node importance |
| `community-detection.md` | Leiden, Louvain, walktrap; seed discipline; undirected requirement; modularity | Finding groups/clusters in a graph |
| `paths-components.md` | Shortest paths, distances, diameter, connected components, reachability | Path/reachability/component questions |
| `bipartite.md` | Two-mode graph construction (`type` attribute), one-mode projection | Two-mode (actor–event) data |
| `visualization.md` | ggraph grammar, seeded layouts, edge/node geoms, faceting | Making static network figures |
| `dataframe-interop.md` | `activate()`/`as_tibble()`, node/edge attributes ↔ tibbles for downstream stats | Moving between graph and tidy tables |
| `gotchas.md` | Silent weight auto-use, seed sensitivity, directed/undirected traps, disconnected-graph pitfalls | Debugging or before trusting a result |
### Reading Order
1. **New to igraph in R?** Start with `quickstart.md` then `dataframe-interop.md`
2. **Computing centrality?** Read `centrality.md` (and `gotchas.md` on weight auto-use)
3. **Detecting communities?** Read `community-detection.md` (seed discipline is mandatory)
4. **Paths / reachability?** Read `paths-components.md`
5. **Two-mode data?** Read `bipartite.md`
6. **Making figures?** Read `visualization.md`
7. **Something surprising?** Check `gotchas.md` first — most surprises are weight
auto-use or an unseeded stochastic step
## Related Skills
| Skill | Relationship |
|-------|-------------|
| `igraph` | Python equivalent — same C core, same algorithms, same semantics for Python pipelines |
| `data-scientist` | Method selection — when/why to use network methods vs. clustering; interpretation guidance |
| `tidyverse` | Data preparation — edge-list and node tables are tibbles; dplyr prepares them and `tbl_graph` round-trips back |
| `ggplot2` | Visualization — ggraph is built on ggplot2; load ggplot2 for themes, scales, and styling |
| `tidymodels` | Non-graph clustering / dimensionality reduction (k-means, PCA, UMAP) when there is no explicit graph structure |
| `sf-terra` | Spatial / road-network routing (sfnetworks, spdep contiguity graphs) — geographic graphs, not general relational graphs |
| `r-python-translation` | Cross-language translation of network code |
**Routing guidance:** Use this skill for general relational/graph data (social
networks, citation graphs, co-occurrence, actor–event structures). For
**road-network routing** (shortest path along a street network) use `sf-terra`
(sfnetworks). For **community detection framed as feature clustering** without an
explicit node/edge graph — e.g., clustering observations by numeric features — use
`tidymodels`, not this skill. For **spatial contiguity weights** (queen/rook
neighbors, distance bands) use `sf-terra` + spdep.
## Quick Decision Trees
### "I need to build a graph from data"
```
Constructing a graph?
+-- From an edge-list tibble -> ./references/quickstart.md
+-- From edge list + separate node table -> ./references/quickstart.md
+-- Directed vs undirected (which to choose) -> ./references/quickstart.md + ./references/gotchas.md
+-- Two-mode (actor-event / bipartite) data -> ./references/bipartite.md
+-- Round-trip graph back to tidy tables -> ./references/dataframe-interop.md
+-- Read/write a graph to file -> ./references/quickstart.md
```
### "I need to measure node importance"
```
Centrality?
+-- Degree (in/out/all) -> ./references/centrality.md
+-- Betweenness / closeness -> ./references/centrality.md (check components first!)
+-- Eigenvector / PageRank -> ./references/centrality.md
+-- Unweighted result but graph has a 'weight' attribute -> ./references/gotchas.md (pass weights = NA)
+-- Weighted centrality (weights = distances) -> ./references/centrality.md
```
### "I need to find groups / communities"
```
Community detection?
+-- Louvain / Leiden (fast modularity) -> ./references/community-detection.md (set.seed first!)
+-- Walktrap (random-walk based) -> ./references/community-detection.md
+-- Directed graph -> convert with as_undirected() first -> ./references/community-detection.md
+-- Reproducible results across runs -> ./references/community-detection.md (seed discipline)
+-- Modularity / evaluating a partition -> ./references/community-detection.md
```
### "I need paths, distances, or components"
```
Paths / reachability?
+-- Shortest path between two nodes -> ./references/paths-components.md
+-- All-pairs distances / diameter -> ./references/paths-components.md
+-- Connected components -> ./references/paths-components.md
+-- Is the graph connected? (before centrality) -> ./references/paths-components.md
```
### "I need to make a network figure"
```
Visualization?
+-- Force-directed layout (FR / KK) -> ./references/visualization.md (set.seed first!)
+-- Color nodes by community / attribute -> ./references/visualization.md
+-- Size nodes by centrality -> ./references/visualization.md
+-- Edge weights / directed arrows -> ./references/visualization.md
+-- Reproducible figure across runs -> ./references/visualization.md (seed discipline)
```
### "I need to move between graphs and tibbles"
```
Graph <-> tidy tables?
+-- Extract node table for downstream stats -> ./references/dataframe-interop.md
+-- Extract edge table -> ./references/dataframe-interop.md
+-- Attach a computed attribute back to nodes -> ./references/dataframe-interop.md
+-- dplyr verbs on nodes/edges (activate) -> ./references/dataframe-interop.md
```
### "Something isn't working"
```
Having issues?
+-- Centrality "ignored" my weights argument / unexpected weighting -> ./references/gotchas.md
+-- Community/layout results differ every run -> ./references/gotchas.md (seed)
+-- cluster_leiden / cluster_louvain error on directed graph -> ./references/gotchas.md
+-- closeness/betweenness gives Inf/NaN or warnings -> ./references/gotchas.md (disconnected)
+-- Directed vs undirected giving surprising numbers -> ./references/gotchas.md
```
## File-First Execution in Research Workflows
In DAAF research pipelines, R network operations follow the **file-first execution
protocol** — code is written to `.R` script files and executed via the
`run_with_capture.sh` wrapper, never run interactively.
**The pattern:**
1. Write network analysis code to `scripts/stage{N}_{type}/{step}_{task-name}.R`
2. Execute via Bash: `bash {BASE_DIR}/scripts/run_with_capture.sh {PROJECT_DIR}/scripts/{script_name}.R`
3. `run_with_capture.sh` detects the `.R` extension and uses `Rscript` automatically
4. stdout/stderr are appended to the script file as comments
5. If a script fails, create a versioned copy (`_a.R`, `_b.R`, etc.) for fixes
Read `agent_reference/SCRIPT_EXECUTION_REFERENCE.md` for the complete protocol.
**R network script structure follows DAAF conventions:**
```r
# --- Config ---
library(igraph)
library(tidygraph)
library(dplyr)
PROJECT_DIR <- "/daaf/research/YYYY-MM-DD_Project"
SEED <- 20260715 # fixed seed for reproducible community detection
# --- Load ---
# INTENT: Build a co-authorship graph from an edge-list tibble
# ASSUMES: edges tibble has columns 'from' and 'to' naming authors
edges <- arrow::read_parquet(file.path(PROJECT_DIR, "data", "coauthor_edges.parquet"))
g <- as_tbl_graph(edges, directed = FALSE)
cat("Nodes:", igraph::gorder(g), " Edges:", igraph::gsize(g), "\n")
# --- Transform ---
# INTENT: Detect communities; graph is unweighted so suppress weight auto-use
# REASONING: cluster_louvain requires an undirected graph (already undirected here)
# ASSUMES: no 'weight' edge attribute; weights = NA makes that explicit
set.seed(SEED) # community detection is stochastic — seed for reproducibility
comm <- cluster_louvain(g, weights = NA)
g <- g |> activate(nodes) |> mutate(community = as.factor(membership(comm)))
# --- Validate ---
stopifnot(igraph::gorder(g) == length(membership(comm)))
cat("Communities found:", length(comm), " Modularity:", round(modularity(comm), 3), "\n")
# --- Save ---
node_tbl <- g |> activate(nodes) |> as_tibble()
arrow::write_parquet(node_tbl, file.path(PROJECT_DIR, "data", "nodes_with_community.parquet"))
cat("Saved: nodes_with_community.parquet\n")
```
## Quick Reference
### Essential Setup
```r
library(igraph) # graph engine (centrality, community, paths)
library(tidygraph) # tbl_graph, activate(), dplyr verbs on graphs
library(ggraph) # grammar-of-graphics network figures (needs container rebuild)
library(dplyr) # data manipulation for node/edge tables
library(ggplot2) # themes/scales for ggraph
```
### Core Operations
| Operation | Code | Package |
|-----------|------|---------|
| Graph from edge tibble | `as_tbl_graph(edges, directed = FALSE)` | tidygraph |
| Graph from igraph directly | `graph_from_data_frame(edges, directed = FALSE, vertices = nodes)` | igraph |
| Node count / edge count | `gorder(g)` / `gsize(g)` | igraph |
| Activate node table | `g \|> activate(nodes)` | tidygraph |
| Node table to tibble | `g \|> activate(nodes) \|> as_tibble()` | tidygraph |
| Degree (in/out/all) | `degree(g, mode = "all")` | igraph |
| Betweenness (unweighted) | `betweenness(g, weights = NA)` | igraph |
| Closeness (check components!) | `closeness(g, weights = NA)` | igraph |
| Eigenvector centrality | `eigen_centrality(g, weights = NA)$vector` | igraph |
| PageRank | `page_rank(g)$vector` | igraph |
| Community (Louvain) | `set.seed(s); cluster_louvain(g, weights = NA)` | igraph |
| Community (Leiden) | `set.seed(s); cluster_leiden(g, objective_function = "modularity")` | igraph |
| Membership vector | `membership(comm)` | igraph |
| Modularity of a partition | `modularity(comm)` | igraph |
| Connected components | `components(g)` | igraph |
| Is connected? | `is_connected(g)` | igraph |
| Shortest path | `shortest_paths(g, from, to)` | igraph |
| Convert to undirected | `as_undirected(g, mode = "collapse")` | igraph |
| Bipartite projection | `bipartite_projection(g)` | igraph |
| Static plot | `set.seed(s); ggraph(g, layout = "fr") + geom_edge_link() + geom_node_point()` | ggraph |
### The Two Non-Negotiables
| Rule | Why | Reference |
|------|-----|-----------|
| **Pass `weights = NA` for unweighted centrality/community** | igraph silently auto-uses a `weight` edge attribute and treats it as **distance** (higher = longer path), not strength | `gotchas.md`, `centrality.md` |
| **`set.seed()` before any stochastic step** | Force-directed layouts and community detection are non-deterministic; unseeded results are irreproducible. igraph's old `srand()` is deprecated/ignored — use `set.seed()` | `gotchas.md`, `community-detection.md`, `visualization.md` |
## Topic Index
| Topic | Reference File |
|-------|---------------|
| tbl_graph construction | `./references/quickstart.md` |
| Edge-list tibble to graph | `./references/quickstart.md` |
| Directed vs undirected choice | `./references/quickstart.md` |
| Graph I/O (read/write) | `./references/quickstart.md` |
| Graph inspection (order, size, attributes) | `./references/quickstart.md` |
| Degree centrality (in/out/all) | `./references/centrality.md` |
| Betweenness centrality | `./references/centrality.md` |
| Closeness centrality | `./references/centrality.md` |
| Eigenvector centrality | `./references/centrality.md` |
| PageRank | `./references/centrality.md` |
| weights = NA discipline | `./references/centrality.md` |
| Component check before centrality | `./references/centrality.md` |
| Louvain community detection | `./references/community-detection.md` |
| Leiden community detection | `./references/community-detection.md` |
| Walktrap community detection | `./references/community-detection.md` |
| Seed discipline (community) | `./references/community-detection.md` |
| Undirected requirement for Leiden/Louvain | `./references/community-detection.md` |
| Modularity | `./references/community-detection.md` |
| Shortest paths | `./references/paths-components.md` |
| Distances / diameter | `./references/paths-components.md` |
| Connected components | `./references/paths-components.md` |
| Reachability | `./references/paths-components.md` |
| Bipartite graph construction | `./references/bipartite.md` |
| One-mode projection | `./references/bipartite.md` |
| ggraph layouts | `./references/visualization.md` |
| Seeded layouts | `./references/visualization.md` |
| Node/edge geoms | `./references/visualization.md` |
| Color by community | `./references/visualization.md` |
| activate() / as_tibble() | `./references/dataframe-interop.md` |
| Node/edge attributes to tibbles | `./references/dataframe-interop.md` |
| dplyr verbs on graphs | `./references/dataframe-interop.md` |
| Silent weight auto-use | `./references/gotchas.md` |
| Seed sensitivity | `./references/gotchas.md` |
| Directed/undirected traps | `./references/gotchas.md` |
| Disconnected-graph centrality | `./references/gotchas.md` |
## Citation
igraph, tidygraph, and ggraph are software; when they are used as primary
analytical tools, include software citations in the report's Software & Tools
references. Pipeline agents should propagate these citations into report
deliverables per `agent_reference/CITATION_REFERENCE.md` (a registry entry for the
igraph ecosystem is maintained there — reference it rather than duplicating).
**igraph (R) requires all three references together.** The installed `citation("igraph")`
CITATION file states verbatim: *"To cite igraph please use these three references."*
The 2006 paper is **not** superseded by the newer ones — the citation is cumulative:
> Csárdi, G. and Nepusz, T. (2006). "The igraph software package for complex network
> research." *InterJournal, Complex Systems*, 1695. https://igraph.org
>
> Antonov, M., Csárdi, G., Horvát, S., Müller, K., Nepusz, T., Noom, D., Salmon, M.,
> Traag, V., Foucault Welles, B., and Zanini, F. (2023). "igraph enables fast and
> robust network analysis across programming languages." *arXiv preprint
> arXiv:2311.10260.* https://doi.org/10.48550/arXiv.2311.10260
>
> Csárdi, G., Nepusz, T., Traag, V., Horvát, S., Zanini, F., Noom, D., Müller, K.,
> Schoch, D., and Salmon, M. (2026). *igraph: Network Analysis and Visualization in R.*
> R package version 2.2.3. https://doi.org/10.5281/zenodo.7682609
> **Note on the 2023 reference:** As of the installed CITATION file (igraph 2.2.3) it
> is an arXiv preprint; cite it as such. The DOI `10.48550/arXiv.2311.10260` is stable
> regardless of eventual journal publication.
BibTeX (reproduce all three):
```bibtex
@Article{,
title = {The igraph software package for complex network research},
author = {G\'abor Cs\'ardi and Tam\'as Nepusz},
journal = {InterJournal},
volume = {Complex Systems},
pages = {1695},
year = {2006},
url = {https://igraph.org},
}
@Article{,
title = {igraph enables fast and robust network analysis across programming languages},
author = {Michael Antonov and G\'abor Cs\'ardi and Szabolcs Horv\'at and Kirill M\"uller
and Tam\'as Nepusz and Daniel Noom and Ma\"elle Salmon and Vincent Traag
and Brooke Foucault Welles and Fabio Zanini},
journal = {arXiv preprint arXiv:2311.10260},
year = {2023},
doi = {10.48550/arXiv.2311.10260},
}
@Manual{,
title = {{igraph}: Network Analysis and Visualization in R},
author = {G\'abor Cs\'ardi and Tam\'as Nepusz and Vincent Traag and Szabolcs Horv\'at
and Fabio Zanini and Daniel Noom and Kirill M\"uller and David Schoch
and Ma\"elle Salmon},
year = {2026},
note = {R package version 2.2.3},
doi = {10.5281/zenodo.7682609},
url = {https://CRAN.R-project.org/package=igraph},
}
```
If tidygraph is used for graph manipulation, additionally cite:
> Pedersen, T.L. (2024). *tidygraph: A Tidy API for Graph Manipulation.* R package
> version 1.3.1. https://CRAN.R-project.org/package=tidygraph
If ggraph is used for network figures, additionally cite:
> Pedersen, T.L. (2025). *ggraph: An Implementation of Grammar of Graphics for Graphs
> and Networks.* R package version 2.2.2. https://CRAN.R-project.org/package=ggraph
**Licenses:** igraph is **GPL-2 (or later)**; tidygraph and ggraph are **MIT**
(`MIT + file LICENSE`). Acknowledge these in the report's software/licensing notes
when the packages are central to the analysis.
**Cite when:** igraph/tidygraph/ggraph are used for centrality, community
detection, path analysis, or network figures central to the analysis.
**Do not cite when:** only used incidentally (e.g., a single degree count as a
descriptive aside).