Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/evamaerey/ggedgelist
Use edgelist flat files as inputs to start building network visualizations with ggraph
https://github.com/evamaerey/ggedgelist
Last synced: 11 days ago
JSON representation
Use edgelist flat files as inputs to start building network visualizations with ggraph
- Host: GitHub
- URL: https://github.com/evamaerey/ggedgelist
- Owner: EvaMaeRey
- License: other
- Created: 2023-10-16T15:04:21.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2023-11-28T16:20:12.000Z (11 months ago)
- Last Synced: 2023-11-28T17:34:51.230Z (11 months ago)
- Language: HTML
- Size: 3.96 MB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
README
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```## Intro {ggedgelist} idea
Here we think about a shortcut to a first looks at networks using a flat, edgelist input that leads straight to a ggplot2 plot (ggraph) space; this uses {tidygraph} and {ggraph} under the hood...
## Step 00 Before getting into it, create an 'interesting' edge list
```{r cars, message=F, warning=F}
library(tidyverse)
library(tidygraph)
library(ggraph)set.seed(12345)
edge_list <-
data.frame(node_to = sample(rep(LETTERS[1:10], 50),
replace = T),
node_from = sample(rep(LETTERS[1:10], 50),
replace = T)) %>%
arrange(node_to, node_from) %>%
count(node_to, node_from) %>%
sample_n(18)head(edge_list)
```## Step 0. Whats the status quo edgelist -> network viz
```{r}
edge_list %>%
as_tbl_graph() %>%
ggraph() +
geom_edge_link(color = "orange") +
geom_node_point(size = 9,
color = "steelblue",
alpha = .8) +
geom_node_text(aes(label = name))# aesthetic mapping for edge characteristics
last_plot() +
geom_edge_link(color = "red",
alpha = .5 ,
aes(edge_width = n))
```## Step 0.a And to also vizualize node atributes
```{r}
node_info <- data.frame(my_nodes = LETTERS[1:10],
ind_child = sample(c(T,F), 10,
replace = T))edge_list %>%
as_tbl_graph() %>%
left_join(node_info %>%
rename(name = my_nodes)) %>%
ggraph() +
geom_edge_link(color = "orange") +
geom_node_point(size = 9,
color = "steelblue",
alpha = .8) +
geom_node_text(aes(label = name))```
# Proposed functions, edgelist -> plotspace feel
```{r ggedgelist}
# get into ggplot2 plot space from edge list data frame
ggedgelist <- function(edgelist, nodelist = NULL, ...)(
# message("'name' a variable created in the 'nodes' dataframe")
if(is.null(nodelist)){
edgelist %>%
tidygraph::as_tbl_graph() %>%
ggraph::ggraph(...)
}else{ # join on nodes attributes if they are available
names(nodelist)[1] <- "name"
edgelist %>%
tidygraph::as_tbl_graph() %>%
dplyr::full_join(nodelist) %>%
ggraph::ggraph(...)
}
)# get a fill viz w edgelist dataframe only
ggedgelist_quick <- function(edgelist, nodelist = NULL, include_names = F, ...){
p <- ggedgelist(edgelist = edgelist,
nodelist = nodelist, ...) +
ggraph::geom_edge_link(color = "orange") +
ggraph::geom_node_point(size = 9,
color = "steelblue",
alpha = .8)
if(include_names){p + ggraph::geom_node_label(aes(label = name))}else{p}
}geom_node_label_auto <- function(...){
ggraph::geom_node_label(aes(label = name), ...)
}geom_node_text_auto <- function(...){
ggraph::geom_node_text(aes(label = name), ...)
}
```# examples w/ proposed functions
## `ggedgelist_quick()`
```{r, out.width="33%", fig.show='hold', message=F}
head(edge_list)
head(node_info)
edge_list %>%
ggedgelist_quick()edge_list %>%
ggedgelist_quick(include_names = T)edge_list %>%
ggedgelist_quick(nodelist = node_info) +
geom_node_point(aes(color = ind_child), size = 10)
```## `ggedgelist()` + `geom_node_label_auto()`
```{r}
edge_list %>%
ggedgelist(layout = "kk") +
geom_edge_link(arrow = arrow(), linetype = "dashed") +
geom_node_tile(width = .18, height = .5) +
geom_node_label_auto()
```# using the ggflowchart example (100% inspiration)
```{r}
# flowcharter example
ggflowchart_example <- tribble(~from, ~to,
"A", "B",
"A", "C",
"A", "D",
"B", "E",
"C", "F",
"F", "G")ggflowchart_example %>%
as_tbl_graph()
```## Start by using quick plot function 'qedgelist2ggraph'
```{r, out.width="33%", fig.show='hold', message=F}
ggflowchart_example %>%
ggedgelist_quick(layout = "stress",
include_names = T)ggflowchart_example %>%
ggedgelist_quick(layout = "tree",
include_names = T)# auto which is default also produces three in this case
ggflowchart_example %>%
ggedgelist_quick(layout = "auto")layer_data(last_plot(), i = 2)
```## Use ggedgelist and geom_edge_* and geom_node_* functions to customize
```{r}
ggflowchart_example %>%
ggedgelist() +
geom_edge_link(linetype = "dashed") +
geom_node_point(size = 12, alpha = .2) +
geom_node_label_auto(fill = "magenta")```
## Capabilities end here. If you need to access powerful network calculation capabilities, step back into the tidygraph world!
```{r}
ggflowchart_example %>%
as_tbl_graph() %>%
mutate(dg_cent = centrality_degree()) %>%
ggraph("stress") +
geom_edge_link(linetype = "dashed") +
geom_node_point(alpha = .2, aes(size = dg_cent)) +
scale_size(range = c(8, 15)) +
geom_node_label_auto(fill = "magenta")```
# Part II. Packaging and documentation 🚧 ✅
## Phase 1. Minimal working package
### Created files for package archetecture with `devtools::create(".")` ✅
### Moved functions R folder? ✅
```{r}
knitr::knit_code$get() |> names()
```Use new {readme2pkg} function to do this from readme... ✅
```{r}
readme2pkg::chunk_to_r("ggedgelist")
```### Added roxygen skeleton? ✅
Use a roxygen skeleton for auto documentation and making sure proposed functions are *exported*.
### Managed dependencies ? ✅
Package dependencies managed, i.e. `depend::function()` in proposed functions and declared in the DESCRIPTION
```{r pkg_dependencies}
usethis::use_package("ggplot2")
usethis::use_package("ggraph")
usethis::use_package("tidygraph")
usethis::use_package("dplyr")
```### Chosen a license? ✅
```{r pkg_license}
usethis::use_mit_license()
```### Run `devtools::check()` and addressed errors? 🚧
```{r pkg_check, results='hide', error=T}
devtools::check(pkg = ".")
```### Build package 🚧
```{r pkg_build}
devtools::build()
```You need to do this before library(mynewpackage) will work.
### Make aspirational part of readme real. 🚧
At this point, you could change eval chunk options to TRUE. You can remove the 🦄 emoji and perhaps replace it with construction site if you are still uncertain of the API, and want to highlight that it is subject to change.
### Add lifecycle badge (experimental)✅
```{r pkg_lifecycle_badge}
usethis::use_lifecycle_badge("experimental")
```## Phase 2: Listen & iterate 🚧
Try to get feedback from experts on API, implementation, default decisions. Is there already work that solves this problem?
## Phase 3: Let things settle
### Settled on examples. Put them in the roxygen skeleton and readme. 🚧
### Written formal tests of functions? 🚧
That would look like this...
```{r test_calc_frequency_works, eval = F}
library(testthat)test_that("calc frequency works", {
expect_equal(calc_frequency("A", 0), 440)
expect_equal(calc_frequency("A", -1), 220)
})
``````{r send_tests, eval = F}
readme2pkg::chunk_to_tests_testthat("test_calc_frequency_works")
```### Have you worked added a description and author information in the DESCRIPTION file? 🚧
### Addressed *all* notes, warnings and errors. 🚧
## Promote to wider audience...
### Package website built? 🚧
### Package website deployed? 🚧
## Phase 3: Harden/commit
### Submit to CRAN? Or don't. 🚧
# Appendix: Reports, Environment
## Description file extract
```{r}
```
## Environment
Here I just want to print the packages and the versions
```{r session_pkgs}
all <- sessionInfo() |> print() |> capture.output()
all[11:17]
```## `devtools::check()` report
```{r report_check, error = T, results="hide", warning=F}
devtools::check(pkg = ".")
```