Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/JohMast/flowmapper
Draw flows (migration, goods, money, information) on ggplots.
https://github.com/JohMast/flowmapper
Last synced: 2 months ago
JSON representation
Draw flows (migration, goods, money, information) on ggplots.
- Host: GitHub
- URL: https://github.com/JohMast/flowmapper
- Owner: JohMast
- License: other
- Created: 2024-02-24T13:02:34.000Z (9 months ago)
- Default Branch: master
- Last Pushed: 2024-09-02T09:19:42.000Z (2 months ago)
- Last Synced: 2024-09-02T11:07:28.202Z (2 months ago)
- Language: R
- Size: 17.1 MB
- Stars: 19
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.Rmd
- Changelog: NEWS.md
- License: LICENSE
Awesome Lists containing this project
- awesome-ggplot2 - flowmapper
README
---
output: github_document
---[![CRAN status](https://www.r-pkg.org/badges/version/flowmapper)](https://CRAN.R-project.org/package=flowmapper)
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,message = FALSE,warning=FALSE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "70%",
dpi=300
# fig.width=7
)
```# flowmapper
flowmapper allows to create ggplots with flowmaps in the style of .
## Installation
You can install the released version of flowmapper from CRAN:
``` r
install.packages("flowmapper")
```Or, you can install the development version of flowmapper like so:
``` r
devtools::install_github("https://github.com/JohMast/flowmapper")
```## Details
flowmapper uses a single function `add_flowmap` to add a flowmap layer to an existing ggplot. `add_flowmap` requires as inputs a single data.frame (or tibble) that contains for every combination of two nodes a and b
- the x and y coordinates of each these nodes,
- a unique id for each of these nodes,
- the intensity of flow between those nodes in both directions (from a to b, and from b to a).
The data.frame should have the following columns:
```{r example}
testdata <-
data.frame(
id_a = c("X1","X2","X3","X3","X1","X2","X2"),
id_b = c("X5","X4","X1","X5","X4","X5","X3"),
xa = c(2,14,10,10,2,14,14),
ya = c(6,10,9,9,6,10,10),
xb = c(10,4,2,10,4,10,10),
yb = c(4,10,6,4,10,4,9),
flow_ab = c(1,2,3,3,1,1,4),
flow_ba = c(2,3,2,5,2,1,5)
)```
The dataframe and the ggplot that the flowmap should be added to are then passed into `add_flowmap`.
```{r c2, warning=FALSE}
library(ggplot2)
plot <- ggplot() # empty ggplotlibrary(flowmapper)
plot |>
add_flowmap(testdata)+
coord_equal() # coord equal is highly recommended to create symmetric shapes
```If the number of nodes is very high, the plot will appear cluttered. In that case, nodes can be clustered and merged by proximity, with `k_nodes` controlling the number of clusters.
```{r t1}
plot |>
add_flowmap(testdata,k_nodes = 4)+
coord_equal()
```Transparency and outline of the arrows can be controlled with the `outline_col` and `alpha` arguments.
```{r t3}
plot |>
add_flowmap(testdata, outline_col = "orange", alpha=0.5)+
coord_equal() # coord equal is highly recommended to create symmetric shapes
```The flow arrows are geom_polygons, with the flow mapped to the fill aesthetic. Thus, the fill can be adjusted like for any geom.
```{r t4}
plot |>
add_flowmap(testdata)+
coord_equal() +
scale_fill_gradient(low="black", high = "red")
```Size of the edges and offset (distance between two paired edges) can be controlled with `edge_width_factor` and `edge_offset_factor` .
```{r t5}
plot |>
add_flowmap(testdata, edge_offset_factor = 4, edge_width_factor = 2)+
coord_equal()
```Finally, the size of the nodes can be adjusted with `node_radius_factor`, and the distance between nodes and edges with `node_buffer_factor`.
```{r t6}
plot |>
add_flowmap(testdata, node_radius_factor = 2, node_buffer_factor = 0.5)+
coord_equal()
```Because the edges are polygons and not linked to an aesthetic, a typical ggplot legend cannot be created for their width. As an alternative, a legend can be added to the bottom of the main panel by using `add_legend` and `legend_col`.
```{r t7}
plot |>
add_flowmap(testdata,add_legend = "bottom",legend_col = "gray20")+
coord_equal()
```The flowmap can be turned into an interactive plot using the [plotly](https://github.com/plotly/plotly.R) library. The names of the nodes and flows are mapped to the `text` aesthetic and can be used in the tooltips.
```{r t8, eval=FALSE, include=TRUE}
library(plotly)
plot <-
plot |>
add_flowmap(testdata)+
coord_equal()
ggplotly(plot,tooltip = c("text","fill"))
```![](man/figures/plotly_example.PNG)
## Example
The code below shows an example of real world data from Switzerland (same data used in [this](https://www.flowmap.blue/15kwLB4baXZ7jpip8q0JjgR6zDoS5Gt3gMLCTUAboQxk?v=46.719075,7.817990,7.51&a=0&d=1&c=0<=1&col=Default&f=45) flowmap). The data contains migration flows between the 26 Cantons of Switzerland.
```{r t9}
library(dplyr,warn.conflicts = FALSE)
library(ggplot2,warn.conflicts = FALSE)
library(sf)
library(flowmapper)# load migration data
data <-
flowmapper::CH_migration_data
head(data)
```As a background for the flow map, a ggplot is created using the administrative boundaries, sourced from the [GADM](https://gadm.org/index.html) dataset.
```{r t10}
cantons <- flowmapper::cantons
st_crs(cantons) <- 3857# basic plot with just the admin units
p <- ggplot(cantons)+
geom_sf(fill=NA,col="gray30",linewidth=0.5) +
ggdark::dark_theme_bw()+
theme(panel.border = element_blank(),
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank())+
labs(title = "Migration in Switzerland 2016",
caption = "Data: Federal Statistical Office, Switzerland")
p
```The flowmap is then added to the base plot by using `add_flowmap`, applying some clustering to reduce the number of nodes from 26 to 10. A custom color scale is applied which matches the dark background.
```{r t11}
p2 <-
p|>
add_flowmap(flowdat = data,
add_legend = "bottom",
edge_width_factor = 0.7,
k_nodes = 10,
outline_col = NA)+
theme(panel.grid = element_blank())+
scale_fill_gradient("Migration",
low = "darkblue",
high="white")
p2
```The flowmap uses the *color* and *fill* aesthetics, which can be limiting when the ggplot also should contain other layers using the same aesthetic. In such cases, the [ggnewscale](https://eliocamp.github.io/ggnewscale/) package can be used to enable a new scale for those aesthetics. The following example shows a flowmap being added to a basemap from the [basemaps](https://jakob.schwalb-willmann.de/basemaps/) package, which itself uses the *fill* aesthetic.
```{r t12}
library(basemaps)p <- basemap_ggplot(cantons,
map_service = "esri",
map_type = "world_hillshade",
alpha=0.3)+
theme_bw()+
theme(
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank())+
scale_x_continuous(expand = expansion(0,0))+
scale_y_continuous(expand = expansion(0,0))+
ggnewscale::new_scale_fill()+
labs(title = "Migration in Switzerland 2016",
caption = "Data: Federal Statistical Office, Switzerland")p|>
add_flowmap(flowdat = data,
edge_width_factor = 0.7,k_nodes = 10,
outline_col = NA)+
theme(panel.grid = element_blank())+
scale_fill_gradient("Migration",low = "gray",high="red")
```