{"id":13711027,"url":"https://teunbrand.github.io/ggarrow/","last_synced_at":"2025-05-06T20:31:34.047Z","repository":{"id":65923550,"uuid":"554305757","full_name":"teunbrand/ggarrow","owner":"teunbrand","description":"ggplot2 extension: more options for drawing arrows","archived":false,"fork":false,"pushed_at":"2024-06-05T20:41:04.000Z","size":16094,"stargazers_count":50,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-07-13T11:22:49.943Z","etag":null,"topics":["ggplot-extension","ggplot2","ggplot2-geom","rstats"],"latest_commit_sha":null,"homepage":"https://teunbrand.github.io/ggarrow/","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/teunbrand.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-19T15:34:44.000Z","updated_at":"2024-08-03T00:03:54.487Z","dependencies_parsed_at":"2023-11-08T23:36:21.949Z","dependency_job_id":"1c9bf8c9-8961-4ac9-8c3d-80a8085aac72","html_url":"https://github.com/teunbrand/ggarrow","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teunbrand%2Fggarrow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teunbrand%2Fggarrow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teunbrand%2Fggarrow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teunbrand%2Fggarrow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teunbrand","download_url":"https://codeload.github.com/teunbrand/ggarrow/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224528328,"owners_count":17326342,"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":["ggplot-extension","ggplot2","ggplot2-geom","rstats"],"created_at":"2024-08-02T23:01:03.620Z","updated_at":"2024-11-13T21:31:24.462Z","avatar_url":"https://github.com/teunbrand.png","language":"R","funding_links":[],"categories":["Plot layers"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  fig.align = \"center\",\n  out.width = \"80%\",\n  dev       = \"ragg_png\",\n  dpi       = 132\n)\n```\n\n# ggarrow \u003cimg src=\"man/figures/logo.png\" align=\"right\" height=\"138\" /\u003e\n\n\u003c!-- badges: start --\u003e\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)\n[![R-CMD-check](https://github.com/teunbrand/ggarrow/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/teunbrand/ggarrow/actions/workflows/R-CMD-check.yaml)\n[![Codecov test coverage](https://codecov.io/gh/teunbrand/ggarrow/branch/main/graph/badge.svg)](https://app.codecov.io/gh/teunbrand/ggarrow?branch=main)\n[![CRAN status](https://www.r-pkg.org/badges/version/ggarrow)](https://CRAN.R-project.org/package=ggarrow)\n\u003c!-- badges: end --\u003e\n\nThe goal of ggarrow is to draw arrows in [{ggplot2}](https://ggplot2.tidyverse.org/). It is a [{ggplot2} extension](https://exts.ggplot2.tidyverse.org/gallery/) package that focusses on specialised geometry layers to expand the toolkit of arrows.\n\n## Installation\n\nYou can install ggarrow from CRAN\n\n``` r\ninstall.packages(\"ggarrow\")\n```\n\nYou can install the development version of ggarrow from [GitHub](https://github.com/) with:\n\n``` r\n# install.packages(\"devtools\")\ndevtools::install_github(\"teunbrand/ggarrow\")\n```\n\n## Arrows\n\nThey're made for pointing at things. The workhorse functionality is in the `geom_arrow()` function that, unsurprisingly, draws arrows. \n\n### Basic arrows\n\n```{r basic_example}\nlibrary(ggarrow)\n\np \u003c- ggplot(whirlpool(5), aes(x, y, colour = group)) +\n  coord_equal() +\n  guides(colour = \"none\")\np + geom_arrow()\n```\n\n### Variable width\n\nArrows, in contrast to vanilla lines, can have variable widths.\n\n```{r variable_width}\np + geom_arrow(aes(linewidth = I(arc))) # Identity scale for linewidth\n```\n\n### Inner arrows\n\nBesides varying linewidths, there is also an option to place arrows along the path. \nYou could draw arbitrarily many of these, but I doubt that will look pretty.\n\n```{r middle_arrows}\np + geom_arrow(arrow_mid = \"head_wings\", mid_place = c(0.25, 0.5, 0.75))\n```\n\n### Ornament styles\n\nYou can also tweak what the arrows should look like.\nThe example below is a bit verbose, but gives an impression of the available options by combining different styles of arrow heads and what are termed 'arrow fins'.\n\n```{r, show_ornaments}\np + geom_arrow(aes(arrow_head = group, arrow_fins = group), linewidth = 2) +\n  scale_arrow_head_discrete(values = list(\n    \"head_wings\",\n    arrow_head_wings(offset = 20, inset = 70),\n    arrow_head_line(lineend = \"parallel\"),\n    arrow_head_line(45, lineend = \"round\"),\n    \"head_minimal\"\n  ), guide = \"none\") +\n  scale_arrow_fins_discrete(values = list(\n    \"fins_feather\",\n    arrow_fins_feather(indent = 0, outdent = 0, height = 1),\n    \"fins_line\",\n    arrow_fins_line(90),\n    \"fins_minimal\"\n  ), guide = \"none\")\n```\n\nThere are some other geoms that mimic bread-and-butter ggplot2 layers, such as `geom_arrow_segment()` and `geom_arrow_curve()`, that add the same arrow functionality on top of the `geom_segment()` and `geom_curve()` layers.\n\n### Chains\n\nAside from these, there is also `geom_arrow_chain()`, which has no equivalent in vanilla ggplot2. It adds arrows in between points, and dodges the endpoints a bit so that they don't seem to touch. In the example below, we can see that we can dodge points of different sizes.\n\n```{r arrow_chain}\nt \u003c- seq(0, 2 * pi, length.out = 11)\nl \u003c- rep(c(1, 0.4), length.out = 11)\n\ndf \u003c- data.frame(\n  x = cos(t) * l,\n  y = sin(t) * l,\n  size = l\n)\n\nggplot(df, aes(x, y, size = size)) +\n  geom_point(colour = 2) +\n  geom_arrow_chain() +\n  coord_equal()\n```\n\n### Theme elements\n\nBecause arrows are almost drop-in replacements for lines, I also included `element_arrow()` as a theme element. With function, you can set any line element in the theme to an arrow, with similar customisation options as the layers.\n\n```{r theme_elements}\np + geom_arrow() +\n  theme(\n    axis.line.x = element_arrow(\n      arrow_head = \"head_wings\", linewidth_head = 1.5, linewidth_fins = 0\n    ),\n    axis.line.y = element_arrow(arrow_head = \"head_line\"),\n    axis.ticks.length = unit(0.4, \"cm\"),\n    axis.ticks.x = element_arrow(linewidth_fins = 0, linewidth_head = 2),\n    axis.ticks.y = element_arrow(arrow_fins = \"head_line\"),\n    panel.grid.major = element_arrow(\n      linewidth_head = 5, linewidth_fins = 0,\n      resect_head = 5, resect_fins = 5, lineend = \"round\"\n    ),\n    panel.grid.minor = element_arrow(\n      linewidth_head = 0, linewidth_fins = 5\n    )\n  )\n```\n\n## Limitations\n\nThe current limitation is that variable width paths don't lend themselves well to jagged paths with short segments. This is because I had to implement linejoins for variable width paths and I barely have high-school level understanding of trigonometry. Consequently, the linejoins look bad with short jagged segments.\n\n```{r jagged}\nggplot(economics, aes(date, unemploy)) +\n  geom_arrow(aes(linewidth = date))\n```\n\nThe best advice I can give for the jagged linejoins is to smooth the data beforehand.\n\n```{r smoothed}\nggplot(economics, aes(date, unemploy)) +\n  geom_arrow(\n    stat = \"smooth\", formula = y ~ x, method = \"loess\", span = 0.05,\n    aes(linewidth = after_stat(x))\n  )\n```\n\nA second limitation is that you cannot use variable widths with different linetypes.\n\n## Dependency statement\n\nThe {ggarrow} package largely takes on the same dependencies as {ggplot2} to keep it on the lightweight side. However, this package wouldn't work at all without the {polyclip} dependency, which is the only one outside {ggplot2}'s imports.\n\n## Related work\n\nOf course, the {grid} package, on which {ggplot2} is build upon, offers some options for arrows.\nThe [{arrowheadr}](https://github.com/wjschne/arrowheadr) package provides some great extensions for arrowheads.\nThe [{vwlines}](https://cran.r-project.org/package=vwline) package that handles variable widths lines much more graciously than this package.\nBoth the [{gggenes}](https://wilkox.org/gggenes/) and [{gggenomes}](https://thackl.github.io/gggenomes/) packages use arrows in a domain-specific context.\nFor vector field visualisation, there is the [{ggquiver}](http://pkg.mitchelloharawild.com/ggquiver/) package.\nThe [{ggarchery}](https://github.com/mdhall272/ggarchery) package also provides extended options for the `geom_segment()` parametrisation of lines.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/teunbrand.github.io%2Fggarrow%2F","html_url":"https://awesome.ecosyste.ms/projects/teunbrand.github.io%2Fggarrow%2F","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/teunbrand.github.io%2Fggarrow%2F/lists"}