{"id":13789081,"url":"https://github.com/schochastics/graphlayouts","last_synced_at":"2025-05-15T04:04:43.570Z","repository":{"id":60721646,"uuid":"148535149","full_name":"schochastics/graphlayouts","owner":"schochastics","description":"new layout algorithms for network visualizations in R","archived":false,"fork":false,"pushed_at":"2025-01-23T13:40:11.000Z","size":23596,"stargazers_count":280,"open_issues_count":3,"forks_count":16,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-10T15:02:28.114Z","etag":null,"topics":["ggraph","graph-algorithms","network-analysis","network-visualization","r"],"latest_commit_sha":null,"homepage":"https://schochastics.github.io/graphlayouts/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schochastics.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-09-12T20:03:02.000Z","updated_at":"2025-05-01T20:43:28.000Z","dependencies_parsed_at":"2023-01-29T22:45:26.517Z","dependency_job_id":"4943efa0-764c-4e4c-b080-e6f19ee64f60","html_url":"https://github.com/schochastics/graphlayouts","commit_stats":{"total_commits":210,"total_committers":5,"mean_commits":42.0,"dds":0.09999999999999998,"last_synced_commit":"f02893d80533bf852c3ab7e01f778f5202492774"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schochastics%2Fgraphlayouts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schochastics%2Fgraphlayouts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schochastics%2Fgraphlayouts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schochastics%2Fgraphlayouts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schochastics","download_url":"https://codeload.github.com/schochastics/graphlayouts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254067355,"owners_count":22009156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ggraph","graph-algorithms","network-analysis","network-visualization","r"],"created_at":"2024-08-03T21:00:58.336Z","updated_at":"2025-05-15T04:04:43.542Z","avatar_url":"https://github.com/schochastics.png","language":"R","readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, echo = FALSE}\nknitr::opts_chunk$set(\n    collapse = TRUE,\n    fig.align = \"center\",\n    out.width = \"80%\",\n    comment = \"#\u003e\",\n    fig.path = \"man/figures/README-\",\n    echo = TRUE,\n    warning = FALSE,\n    message = FALSE\n)\n```\n\n# graphlayouts  \u003cimg src=\"man/figures/logo.png\" align=\"right\"/\u003e\n\n[![R-CMD-check](https://github.com/schochastics/graphlayouts/workflows/R-CMD-check/badge.svg)](https://github.com/schochastics/graphlayouts/actions)\n[![CRAN status](https://www.r-pkg.org/badges/version/graphlayouts)](https://cran.r-project.org/package=graphlayouts)\n[![Downloads](https://cranlogs.r-pkg.org/badges/graphlayouts)](https://CRAN.R-project.org/package=graphlayouts)\n[![Total Downloads](https://cranlogs.r-pkg.org/badges/grand-total/graphlayouts)](https://CRAN.R-project.org/package=graphlayouts)\n[![Codecov test coverage](https://codecov.io/gh/schochastics/graphlayouts/branch/main/graph/badge.svg)](https://app.codecov.io/gh/schochastics/graphlayouts?branch=main)\n[![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.7870213.svg)](https://doi.org/10.5281/zenodo.7870213)\n[![JOSS](https://joss.theoj.org/papers/10.21105/joss.05238/status.svg)](https://doi.org/10.21105/joss.05238)\n\n\nThis package implements some graph layout algorithms that are not available\nin `igraph`.\n\n**A detailed introductory tutorial for graphlayouts and ggraph can be found [here](https://schochastics.github.io/netVizR/).** \n\nThe package implements the following algorithms:\n\n- Stress majorization ([Paper](https://graphviz.gitlab.io/_pages/Documentation/GKN04.pdf))\n- Quadrilateral backbone layout ([Paper](https://doi.org/10.7155/jgaa.00370))\n- flexible radial layouts ([Paper](https://www.uni-konstanz.de/algo/publications/bp-mfrl-11.pdf))\n- sparse stress ([Paper](https://arxiv.org/abs/1608.08909))\n- pivot MDS ([Paper](https://doi.org/10.1007/978-3-540-70904-6_6))\n- dynamic layout for longitudinal data ([Paper](https://doi.org/10.1016/j.socnet.2011.06.002))\n- spectral layouts (adjacency/Laplacian)\n- a simple multilevel layout\n- a layout algorithm using UMAP\n- group based centrality and focus layouts which keeps groups of nodes close in the same range on the concentric circle\n\n## Install\n```{r install,eval=FALSE}\n# dev version\nremotes::install_github(\"schochastics/graphlayouts\")\n\n# CRAN\ninstall.packages(\"graphlayouts\")\n```\n\n\n## Stress Majorization: Connected Network  \n\n*This example is a bit of a special case since it exploits some weird issues in igraph.* \n```{r example}\nlibrary(igraph)\nlibrary(ggraph)\nlibrary(graphlayouts)\n\nset.seed(666)\npa \u003c- sample_pa(1000, 1, 1, directed = F)\n\nggraph(pa, layout = \"nicely\") +\n    geom_edge_link0(width = 0.2, colour = \"grey\") +\n    geom_node_point(col = \"black\", size = 0.3) +\n    theme_graph()\n\nggraph(pa, layout = \"stress\") +\n    geom_edge_link0(width = 0.2, colour = \"grey\") +\n    geom_node_point(col = \"black\", size = 0.3) +\n    theme_graph()\n```\n\n## Stress Majorization: Unconnected Network\n\nStress majorization also works for networks with several components. It relies \non a bin packing algorithm to efficiently put the components in a rectangle, rather than a circle.\n\n```{r example_un}\nset.seed(666)\ng \u003c- disjoint_union(\n    sample_pa(10, directed = FALSE),\n    sample_pa(20, directed = FALSE),\n    sample_pa(30, directed = FALSE),\n    sample_pa(40, directed = FALSE),\n    sample_pa(50, directed = FALSE),\n    sample_pa(60, directed = FALSE),\n    sample_pa(80, directed = FALSE)\n)\n\nggraph(g, layout = \"nicely\") +\n    geom_edge_link0() +\n    geom_node_point() +\n    theme_graph()\n\nggraph(g, layout = \"stress\", bbox = 40) +\n    geom_edge_link0() +\n    geom_node_point() +\n    theme_graph()\n```\n\n## Backbone Layout\n\nBackbone layouts are helpful for drawing hairballs. \n\n```{r hairball,eval = FALSE}\nset.seed(665)\n# create network with a group structure\ng \u003c- sample_islands(9, 40, 0.4, 15)\ng \u003c- simplify(g)\nV(g)$grp \u003c- as.character(rep(1:9, each = 40))\n\nggraph(g, layout = \"stress\") +\n    geom_edge_link0(colour = rgb(0, 0, 0, 0.5), width = 0.1) +\n    geom_node_point(aes(col = grp)) +\n    scale_color_brewer(palette = \"Set1\") +\n    theme_graph() +\n    theme(legend.position = \"none\")\n```\n\n\u003cimg src=\"man/figures/README-hairball-1.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\n\nThe backbone layout helps to uncover potential group structures based on edge \nembeddedness and puts more emphasis on this structure in the layout.\n\n```{r backbone,eval=FALSE}\nbb \u003c- layout_as_backbone(g, keep = 0.4)\nE(g)$col \u003c- FALSE\nE(g)$col[bb$backbone] \u003c- TRUE\n\nggraph(g, layout = \"manual\", x = bb$xy[, 1], y = bb$xy[, 2]) +\n    geom_edge_link0(aes(col = col), width = 0.1) +\n    geom_node_point(aes(col = grp)) +\n    scale_color_brewer(palette = \"Set1\") +\n    scale_edge_color_manual(values = c(rgb(0, 0, 0, 0.3), rgb(0, 0, 0, 1))) +\n    theme_graph() +\n    theme(legend.position = \"none\")\n```\n\n\u003cimg src=\"man/figures/README-backbone-1.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\n\n## Radial Layout with Focal Node\n\nThe function `layout_with_focus()` creates a radial layout around a focal node.\nAll nodes with the same distance from the focal node are on the same circle.\n\n```{r flex_focus,eval=FALSE}\nlibrary(igraphdata)\nlibrary(patchwork)\ndata(\"karate\")\n\np1 \u003c- ggraph(karate, layout = \"focus\", focus = 1) +\n    draw_circle(use = \"focus\", max.circle = 3) +\n    geom_edge_link0(edge_color = \"black\", edge_width = 0.3) +\n    geom_node_point(aes(fill = as.factor(Faction)), size = 2, shape = 21) +\n    scale_fill_manual(values = c(\"#8B2323\", \"#EEAD0E\")) +\n    theme_graph() +\n    theme(legend.position = \"none\") +\n    coord_fixed() +\n    labs(title = \"Focus on Mr. Hi\")\n\np2 \u003c- ggraph(karate, layout = \"focus\", focus = 34) +\n    draw_circle(use = \"focus\", max.circle = 4) +\n    geom_edge_link0(edge_color = \"black\", edge_width = 0.3) +\n    geom_node_point(aes(fill = as.factor(Faction)), size = 2, shape = 21) +\n    scale_fill_manual(values = c(\"#8B2323\", \"#EEAD0E\")) +\n    theme_graph() +\n    theme(legend.position = \"none\") +\n    coord_fixed() +\n    labs(title = \"Focus on John A.\")\n\np1 + p2\n```\n\n\u003cimg src=\"man/figures/README-flex_focus-1.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\n\n## Radial Centrality Layout\n\nThe function `layout_with_centrality` creates a radial layout around the node with the\nhighest centrality value. The further outside a node is, the more peripheral it is.\n\n```{r flex_cent}\nlibrary(igraphdata)\nlibrary(patchwork)\ndata(\"karate\")\n\nbc \u003c- betweenness(karate)\np1 \u003c- ggraph(karate, layout = \"centrality\", centrality = bc, tseq = seq(0, 1, 0.15)) +\n    draw_circle(use = \"cent\") +\n    annotate_circle(bc, format = \"\", pos = \"bottom\") +\n    geom_edge_link0(edge_color = \"black\", edge_width = 0.3) +\n    geom_node_point(aes(fill = as.factor(Faction)), size = 2, shape = 21) +\n    scale_fill_manual(values = c(\"#8B2323\", \"#EEAD0E\")) +\n    theme_graph() +\n    theme(legend.position = \"none\") +\n    coord_fixed() +\n    labs(title = \"betweenness centrality\")\n\n\ncc \u003c- closeness(karate)\np2 \u003c- ggraph(karate, layout = \"centrality\", centrality = cc, tseq = seq(0, 1, 0.2)) +\n    draw_circle(use = \"cent\") +\n    annotate_circle(cc, format = \"scientific\", pos = \"bottom\") +\n    geom_edge_link0(edge_color = \"black\", edge_width = 0.3) +\n    geom_node_point(aes(fill = as.factor(Faction)), size = 2, shape = 21) +\n    scale_fill_manual(values = c(\"#8B2323\", \"#EEAD0E\")) +\n    theme_graph() +\n    theme(legend.position = \"none\") +\n    coord_fixed() +\n    labs(title = \"closeness centrality\")\n\np1 + p2\n```\n\n## Large graphs\n\n`graphlayouts` implements two algorithms for visualizing large networks (\u003c100k nodes).\n`layout_with_pmds()` is similar to `layout_with_mds()` but performs the multidimensional scaling\nonly with a small number of pivot nodes. Usually, 50-100 are enough to obtain similar results to the\nfull MDS.\n\n`layout_with_sparse_stress()` performs stress majorization only with a small number of pivots (~50-100).\nThe runtime performance is inferior to pivotMDS but the quality is far superior. \n\nA comparison of runtimes and layout quality can be found in the [wiki](https://github.com/schochastics/graphlayouts/wiki/)  \n**tl;dr**: both layout algorithms appear to be faster than the fastest igraph algorithm `layout_with_drl()`.\n\nBelow are two examples of layouts generated for large graphs using `layout_with_sparse_stress()`\n\n\u003cimg src=\"man/figures/rt-net.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\nA retweet network with 18k nodes and 61k edges\n\n\u003cimg src=\"man/figures/squad_network2022_small.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\nA network of football players with 165K nodes and 6M edges.\n\n## dynamic layouts\n\n`layout_as_dynamic()` allows you to visualize snapshots of longitudinal network data. Nodes are anchored \nwith a reference layout and only moved slightly in each wave depending on deleted/added edges. \nIn this way, it is easy to track down specific nodes throughout time. Use `patchwork` to put the \nindividual plots next to each other.\n\n```{r dynamic,eval = FALSE}\n# remotes::install_github(\"schochastics/networkdata\")\nlibrary(networkdata)\n# longitudinal dataset of friendships in a school class\ndata(\"s50\")\n\nxy \u003c- layout_as_dynamic(s50, alpha = 0.2)\npList \u003c- vector(\"list\", length(s50))\n\nfor (i in seq_along(s50)) {\n    pList[[i]] \u003c- ggraph(s50[[i]], layout = \"manual\", x = xy[[i]][, 1], y = xy[[i]][, 2]) +\n        geom_edge_link0(edge_width = 0.6, edge_colour = \"grey66\") +\n        geom_node_point(shape = 21, aes(fill = as.factor(smoke)), size = 3) +\n        geom_node_text(aes(label = 1:50), repel = T) +\n        scale_fill_manual(\n            values = c(\"forestgreen\", \"grey25\", \"firebrick\"),\n            labels = c(\"no\", \"occasional\", \"regular\"),\n            name = \"smoking\",\n            guide = ifelse(i != 2, \"none\", \"legend\")\n        ) +\n        theme_graph() +\n        theme(legend.position = \"bottom\") +\n        labs(title = paste0(\"Wave \", i))\n}\nwrap_plots(pList)\n```\n\u003cimg src=\"man/figures/dynamic_ex.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\n\n## Layout manipulation\n\nThe functions `layout_mirror()` and `layout_rotate()` can be used to manipulate an existing layout\n\n\u003cimg src=\"man/figures/layout_manipulation.png\" width=\"80%\" style=\"display: block; margin: auto;\" /\u003e\n\n# How to reach out? \n\n### Where do I report bugs?\n\nSimply [open an issue](https://github.com/schochastics/graphlayouts/issues/new) on GitHub.\n\n### How do I contribute to the package?\n\nIf you have an idea (but no code yet), [open an issue](https://github.com/schochastics/graphlayouts/issues/new) on GitHub. If you want to contribute with a specific feature and have the code ready, fork the repository, add your code, and create a pull request.\n\n### Do you need support?\n\nThe easiest way is to [open an issue](https://github.com/schochastics/graphlayouts/issues/new) - this way, your question is also visible to others who may face similar problems.\n\n### Code of Conduct\n\nPlease note that the graphlayouts project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.\n","funding_links":[],"categories":["R","Network Visualization"],"sub_categories":["Miscellaneous"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschochastics%2Fgraphlayouts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschochastics%2Fgraphlayouts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschochastics%2Fgraphlayouts/lists"}