Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mikemahoney218/dendro
dendro: An experimental tree class in S7
https://github.com/mikemahoney218/dendro
r s7 tree-structure
Last synced: 4 days ago
JSON representation
dendro: An experimental tree class in S7
- Host: GitHub
- URL: https://github.com/mikemahoney218/dendro
- Owner: mikemahoney218
- License: other
- Created: 2023-02-23T16:01:11.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2023-03-05T01:34:06.000Z (almost 2 years ago)
- Last Synced: 2024-11-08T12:48:32.391Z (about 2 months ago)
- Topics: r, s7, tree-structure
- Language: R
- Homepage: https://mikemahoney218.github.io/dendro/
- Size: 375 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.Rmd
- Contributing: .github/CONTRIBUTING.md
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Support: .github/SUPPORT.md
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%"
)
```# dendro
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
[![CRAN status](https://www.r-pkg.org/badges/version/dendro)](https://CRAN.R-project.org/package=dendro)
[![Codecov test coverage](https://codecov.io/gh/mikemahoney218/dendro/branch/main/graph/badge.svg)](https://app.codecov.io/gh/mikemahoney218/dendro?branch=main)
[![R-CMD-check](https://github.com/mikemahoney218/dendro/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/mikemahoney218/dendro/actions/workflows/R-CMD-check.yaml)dendro is an experimental package I wrote to play around with tree structures and the new (as of this writing) [S7](https://github.com/RConsortium/OOP-WG/) class system. It's not intended for serious workloads, but rather as a way for me to kick the wheels on S7 and toy with recursive operations.
## Installation
You can install the development version of dendro like so:
``` r
# install.packages("remotes")
remotes::install_github("RConsortium/OOP-WG")
remotes::install_github("mikemahoney218/dendro")
```## Example
The core of the dendro package lives in two S7 classes, `node()` and `tree()`. The node class has four slots: the index value of the node within the tree, the index of the node's parent, and the index of any children the node has, as well as a list slot for any attributes you want to attach to the node:
```{r example}
library(dendro)node(
index = 1L,
value = list(),
parent = 0L,
children = 2L
)
```Nodes are almost entirely unvalidated -- there's no requirement a parent knows about all its children, that a node's parent exists, that the node's index is unique, or that its index corresponds to its location in a tree. Node-creating code is responsible for those validations.
The tree class is slightly more interesting. Its constructor function takes a list of nodes:
```{r}
tree(list(node(1L)))
```The tree class also doesn't do a ton of validation; it only checks to make sure that every node (save for one, the root node) has a parent. However, this class also comes with a few useful dynamic slots: `size`, the number of nodes in the tree; `node_indices`, a vector of all `index` values in the nodes list; `next_idx`, a safe position for the next node to be inserted at, and `root`, the index of the root node in the nodes list.
There's also a handful of methods defined for tree classes. For instance, `add_node()` will automatically add a node at the next available index, for programmatic tree construction:
```{r}
example_tree <- tree() |>
add_node(name = "root") |>
add_node(list(), parent = 1L) |>
add_node(list(), parent = 1L) |>
add_node(list(), parent = 2L) |>
add_node(list(), parent = 4L)example_tree
```Note that `add_node()` is relatively slow, as the tree is re-validated after each call to `add_node()`. To make an entirely new tree from scratch, it's usually faster to call `tree()` with a list of nodes instead.
You can call `drop_node()` to drop nodes from the tree. Note that all descendants of the node will be dropped as well, as dendro doesn't allow multiple roots in a tree:
```{r}
example_tree |>
drop_node(1)
``````{r}
# Get the depth of a node in the tree
example_tree |>
node_depth(5)# Get the distance between two nodes in the tree
example_tree |>
distance_to_target(1, 5)# Get the indices of the children for a node
example_tree |>
get_children(1)# Get the indices of _all_ descendants for a node
example_tree |>
get_all_descendants(1)# Get node objects from a tree
example_tree |>
get_nodes(1)# Get the value slot of a node object from a tree
example_tree |>
get_node_values(1)
```There's also a function, `as_tree`, for converting data frames to tree formats:
```{r}
data.frame(x = letters[1:4], y = letters[25:26]) |>
as_tree(c("x", "y"), root_name = "root")data.frame(x = letters[1:4], y = letters[25:26]) |>
as_tree(c("y", "x"), root_name = "root")
```