bigtree

✨ Construct¢

Construct Tree from list, dictionary, and pandas DataFrame.

To decide which method to use, consider your data type and data values.

Tree Construct MethodsΒΆ

Construct Tree from

Using full path

Using parent-child relation

Add node attributes

String

str_to_tree

NA

No

List

list_to_tree

list_to_tree_by_relation

No

Dictionary

dict_to_tree

nested_dict_to_tree

Yes

DataFrame

dataframe_to_tree

dataframe_to_tree_by_relation

Yes

To add attributes to existing tree,

Tree Add Attributes MethodsΒΆ

Add attributes from

Using full path

Using node name

String

add_path_to_tree

NA

Dictionary

add_dict_to_tree_by_path

add_dict_to_tree_by_name

DataFrame

add_dataframe_to_tree_by_path

add_dataframe_to_tree_by_name

Note

If attributes are added to existing tree using full path, paths that previously did not exist will be added.
If attributes are added to existing tree using node name, names that previously did not exist will not be created.

These functions are not standalone functions. Under the hood, they have the following dependency,

Tree Constructor Dependency Diagram

Functions:

add_dataframe_to_tree_by_name(tree,Β data[,Β ...])

Add attributes to tree, return new root of tree.

add_dataframe_to_tree_by_path(tree,Β data[,Β ...])

Add nodes and attributes to tree in-place, return root of tree.

add_dict_to_tree_by_name(tree,Β name_attrs[,Β ...])

Add attributes to tree, return new root of tree.

add_dict_to_tree_by_path(tree,Β path_attrs[,Β ...])

Add nodes and attributes to tree in-place, return root of tree.

add_path_to_tree(tree,Β path[,Β sep,Β ...])

Add nodes and attributes to existing tree in-place, return node of added path.

dataframe_to_tree(data[,Β path_col,Β ...])

Construct tree from pandas DataFrame using path, return root of tree.

dataframe_to_tree_by_relation(data[,Β ...])

Construct tree from pandas DataFrame using parent and child names, return root of tree.

dict_to_tree(path_attrs[,Β sep,Β ...])

Construct tree from nested dictionary using path, key: path, value: dict of attribute name and attribute value.

list_to_tree(paths[,Β sep,Β ...])

Construct tree from list of path strings.

list_to_tree_by_relation(relations[,Β ...])

Construct tree from list of tuple containing parent-child names.

nested_dict_to_tree(node_attrs[,Β name_key,Β ...])

Construct tree from nested recursive dictionary.

str_to_tree(tree_string[,Β tree_prefix_list,Β ...])

Construct tree from tree string

bigtree.tree.construct.add_dataframe_to_tree_by_name(tree: Node, data: DataFrame, name_col: str = '', attribute_cols: List[str] = [], join_type: str = 'left') NodeΒΆ

Add attributes to tree, return new root of tree.

name_col and attribute_cols specify columns for node name and attributes to add to existing tree. If columns are not specified, the first column will be taken as name column and all other columns as attributes.

Function can return all existing tree nodes or only tree nodes that are in the input data node names. Input data node names that are not existing node names will be ignored. Note that if multiple nodes have the same name, attributes will be added to all nodes sharing same name.

>>> import pandas as pd
>>> from bigtree import add_dataframe_to_tree_by_name, Node
>>> root = Node("a")
>>> b = Node("b", parent=root)
>>> name_data = pd.DataFrame([
...     ["a", 90],
...     ["b", 65],
... ],
...     columns=["NAME", "age"]
... )
>>> root = add_dataframe_to_tree_by_name(root, name_data)
>>> root.show(attr_list=["age"])
a [age=90]
└── b [age=65]
Parameters:
  • tree (Node) – existing tree

  • data (pd.DataFrame) – data containing node name and attribute information

  • name_col (str) – column of data containing name information, if not set, it will take the first column of data

  • attribute_cols (List[str]) – column(s) of data containing node attribute information, if not set, it will take all columns of data except path_col

  • join_type (str) – join type with attribute, default of β€˜left’ takes existing tree nodes, if join_type is set to β€˜inner’ it will only take tree nodes with attributes and drop the other nodes

Returns:

(Node)

bigtree.tree.construct.add_dataframe_to_tree_by_path(tree: Node, data: DataFrame, path_col: str = '', attribute_cols: List[str] = [], sep: str = '/', duplicate_name_allowed: bool = True) NodeΒΆ

Add nodes and attributes to tree in-place, return root of tree.

path_col and attribute_cols specify columns for node path and attributes to add to existing tree. If columns are not specified, path_col takes first column and all other columns are attribute_cols

Path in path column should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

  • Path separator sep is for the input path and can differ from existing tree.

Path in path column can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc. and should not start with another root node.

>>> import pandas as pd
>>> from bigtree import add_dataframe_to_tree_by_path, Node
>>> root = Node("a")
>>> path_data = pd.DataFrame([
...     ["a", 90],
...     ["a/b", 65],
...     ["a/c", 60],
...     ["a/b/d", 40],
...     ["a/b/e", 35],
...     ["a/c/f", 38],
...     ["a/b/e/g", 10],
...     ["a/b/e/h", 6],
... ],
...     columns=["PATH", "age"]
... )
>>> root = add_dataframe_to_tree_by_path(root, path_data)
>>> root.show(attr_list=["age"])
a [age=90]
β”œβ”€β”€ b [age=65]
β”‚   β”œβ”€β”€ d [age=40]
β”‚   └── e [age=35]
β”‚       β”œβ”€β”€ g [age=10]
β”‚       └── h [age=6]
└── c [age=60]
    └── f [age=38]
Parameters:
  • tree (Node) – existing tree

  • data (pd.DataFrame) – data containing node path and attribute information

  • path_col (str) – column of data containing path_name information, if not set, it will take the first column of data

  • attribute_cols (List[str]) – columns of data containing node attribute information, if not set, it will take all columns of data except path_col

  • sep (str) – path separator for input path_col

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

Returns:

(Node)

bigtree.tree.construct.add_dict_to_tree_by_name(tree: Node, name_attrs: Dict[str, Dict[str, Any]], join_type: str = 'left') NodeΒΆ

Add attributes to tree, return new root of tree. Adds to existing tree from nested dictionary, key: name, value: dict of attribute name and attribute value.

Function can return all existing tree nodes or only tree nodes that are in the input dictionary keys depending on join type. Input dictionary keys that are not existing node names will be ignored. Note that if multiple nodes have the same name, attributes will be added to all nodes sharing the same name.

>>> from bigtree import Node, add_dict_to_tree_by_name
>>> root = Node("a")
>>> b = Node("b", parent=root)
>>> name_dict = {
...     "a": {"age": 90},
...     "b": {"age": 65},
... }
>>> root = add_dict_to_tree_by_name(root, name_dict)
>>> root.show(attr_list=["age"])
a [age=90]
└── b [age=65]
Parameters:
  • tree (Node) – existing tree

  • name_attrs (Dict[str, Dict[str, Any]]) – dictionary containing node name and attribute information, key: node name, value: dict of node attribute name and attribute value

  • join_type (str) – join type with attribute, default of β€˜left’ takes existing tree nodes, if join_type is set to β€˜inner’ it will only take tree nodes that are in name_attrs key and drop others

Returns:

(Node)

bigtree.tree.construct.add_dict_to_tree_by_path(tree: Node, path_attrs: Dict[str, Dict[str, Any]], sep: str = '/', duplicate_name_allowed: bool = True) NodeΒΆ

Add nodes and attributes to tree in-place, return root of tree. Adds to existing tree from nested dictionary, key: path, value: dict of attribute name and attribute value.

Path should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

  • Path separator sep is for the input path and can differ from existing tree.

Path can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc. and should not start with another root node.

>>> from bigtree import Node, add_dict_to_tree_by_path
>>> root = Node("a")
>>> path_dict = {
...     "a": {"age": 90},
...     "a/b": {"age": 65},
...     "a/c": {"age": 60},
...     "a/b/d": {"age": 40},
...     "a/b/e": {"age": 35},
...     "a/c/f": {"age": 38},
...     "a/b/e/g": {"age": 10},
...     "a/b/e/h": {"age": 6},
... }
>>> root = add_dict_to_tree_by_path(root, path_dict)
>>> root.show()
a
β”œβ”€β”€ b
β”‚   β”œβ”€β”€ d
β”‚   └── e
β”‚       β”œβ”€β”€ g
β”‚       └── h
└── c
    └── f
Parameters:
  • tree (Node) – existing tree

  • path_attrs (Dict[str, Dict[str, Any]]) – dictionary containing node path and attribute information, key: node path, value: dict of node attribute name and attribute value

  • sep (str) – path separator for input path_attrs

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

Returns:

(Node)

bigtree.tree.construct.add_path_to_tree(tree: Node, path: str, sep: str = '/', duplicate_name_allowed: bool = True, node_attrs: Dict[str, Any] = {}) NodeΒΆ

Add nodes and attributes to existing tree in-place, return node of added path. Adds to existing tree from list of path strings.

Path should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

  • Path separator sep is for the input path and can differ from existing tree.

Path can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc., and should not start with another root node.

>>> from bigtree import add_path_to_tree, Node
>>> root = Node("a")
>>> add_path_to_tree(root, "a/b/c")
Node(/a/b/c, )
>>> root.show()
a
└── b
    └── c
Parameters:
  • tree (Node) – existing tree

  • path (str) – path to be added to tree

  • sep (str) – path separator for input path

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

  • node_attrs (Dict[str, Any]) – attributes to add to node, key: attribute name, value: attribute value, optional

Returns:

(Node)

bigtree.tree.construct.dataframe_to_tree(data: ~pandas.core.frame.DataFrame, path_col: str = '', attribute_cols: ~typing.List[str] = [], sep: str = '/', duplicate_name_allowed: bool = True, node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from pandas DataFrame using path, return root of tree.

path_col and attribute_cols specify columns for node path and attributes to construct tree. If columns are not specified, path_col takes first column and all other columns are attribute_cols.

Path in path column can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

Path in path column should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc. and should not start with another root node.

>>> import pandas as pd
>>> from bigtree import dataframe_to_tree
>>> path_data = pd.DataFrame([
...     ["a", 90],
...     ["a/b", 65],
...     ["a/c", 60],
...     ["a/b/d", 40],
...     ["a/b/e", 35],
...     ["a/c/f", 38],
...     ["a/b/e/g", 10],
...     ["a/b/e/h", 6],
... ],
...     columns=["PATH", "age"]
... )
>>> root = dataframe_to_tree(path_data)
>>> root.show(attr_list=["age"])
a [age=90]
β”œβ”€β”€ b [age=65]
β”‚   β”œβ”€β”€ d [age=40]
β”‚   └── e [age=35]
β”‚       β”œβ”€β”€ g [age=10]
β”‚       └── h [age=6]
└── c [age=60]
    └── f [age=38]
Parameters:
  • data (pd.DataFrame) – data containing path and node attribute information

  • path_col (str) – column of data containing path_name information, if not set, it will take the first column of data

  • attribute_cols (List[str]) – columns of data containing node attribute information, if not set, it will take all columns of data except path_col

  • sep (str) – path separator of input path_col and created tree, defaults to /

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.dataframe_to_tree_by_relation(data: ~pandas.core.frame.DataFrame, child_col: str = '', parent_col: str = '', attribute_cols: ~typing.List[str] = [], allow_duplicates: bool = False, node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from pandas DataFrame using parent and child names, return root of tree.

Since tree is created from parent-child names, only names of leaf nodes may be repeated. Error will be thrown if names of intermediate nodes are repeated as there will be confusion. This error can be ignored by setting allow_duplicates to be True.

child_col and parent_col specify columns for child name and parent name to construct tree. attribute_cols specify columns for node attribute for child name. If columns are not specified, child_col takes first column, parent_col takes second column, and all other columns are attribute_cols.

>>> import pandas as pd
>>> from bigtree import dataframe_to_tree_by_relation
>>> relation_data = pd.DataFrame([
...     ["a", None, 90],
...     ["b", "a", 65],
...     ["c", "a", 60],
...     ["d", "b", 40],
...     ["e", "b", 35],
...     ["f", "c", 38],
...     ["g", "e", 10],
...     ["h", "e", 6],
... ],
...     columns=["child", "parent", "age"]
... )
>>> root = dataframe_to_tree_by_relation(relation_data)
>>> root.show(attr_list=["age"])
a [age=90]
β”œβ”€β”€ b [age=65]
β”‚   β”œβ”€β”€ d [age=40]
β”‚   └── e [age=35]
β”‚       β”œβ”€β”€ g [age=10]
β”‚       └── h [age=6]
└── c [age=60]
    └── f [age=38]
Parameters:
  • data (pd.DataFrame) – data containing path and node attribute information

  • child_col (str) – column of data containing child name information, defaults to None if not set, it will take the first column of data

  • parent_col (str) – column of data containing parent name information, defaults to None if not set, it will take the second column of data

  • attribute_cols (List[str]) – columns of data containing node attribute information, if not set, it will take all columns of data except child_col and parent_col

  • allow_duplicates (bool) – allow duplicate intermediate nodes such that child node will be tagged to multiple parent nodes, defaults to False

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.dict_to_tree(path_attrs: ~typing.Dict[str, ~typing.Any], sep: str = '/', duplicate_name_allowed: bool = True, node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from nested dictionary using path, key: path, value: dict of attribute name and attribute value.

Path should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

Path can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc. and should not start with another root node.

>>> from bigtree import dict_to_tree
>>> path_dict = {
...     "a": {"age": 90},
...     "a/b": {"age": 65},
...     "a/c": {"age": 60},
...     "a/b/d": {"age": 40},
...     "a/b/e": {"age": 35},
...     "a/c/f": {"age": 38},
...     "a/b/e/g": {"age": 10},
...     "a/b/e/h": {"age": 6},
... }
>>> root = dict_to_tree(path_dict)
>>> root.show(attr_list=["age"])
a [age=90]
β”œβ”€β”€ b [age=65]
β”‚   β”œβ”€β”€ d [age=40]
β”‚   └── e [age=35]
β”‚       β”œβ”€β”€ g [age=10]
β”‚       └── h [age=6]
└── c [age=60]
    └── f [age=38]
Parameters:
  • path_attrs (Dict[str, Any]) – dictionary containing path and node attribute information, key: path, value: dict of tree attribute and attribute value

  • sep (str) – path separator of input path_attrs and created tree, defaults to /

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.list_to_tree(paths: ~typing.Iterable[str], sep: str = '/', duplicate_name_allowed: bool = True, node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from list of path strings.

Path should contain Node name, separated by sep.
  • For example: Path string β€œa/b” refers to Node(β€œb”) with parent Node(β€œa”).

Path can start from root node name, or start with sep.
  • For example: Path string can be β€œ/a/b” or β€œa/b”, if sep is β€œ/”.

All paths should start from the same root node.
  • For example: Path strings should be β€œa/b”, β€œa/c”, β€œa/b/d” etc. and should not start with another root node.

>>> from bigtree import list_to_tree
>>> path_list = ["a/b", "a/c", "a/b/d", "a/b/e", "a/c/f", "a/b/e/g", "a/b/e/h"]
>>> root = list_to_tree(path_list)
>>> root.show()
a
β”œβ”€β”€ b
β”‚   β”œβ”€β”€ d
β”‚   └── e
β”‚       β”œβ”€β”€ g
β”‚       └── h
└── c
    └── f
Parameters:
  • paths (Iterable[str]) – list containing path strings

  • sep (str) – path separator for input paths and created tree, defaults to /

  • duplicate_name_allowed (bool) – indicator if nodes with duplicate Node name is allowed, defaults to True

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.list_to_tree_by_relation(relations: ~typing.Iterable[~typing.Tuple[str, str]], allow_duplicates: bool = False, node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from list of tuple containing parent-child names.

Since tree is created from parent-child names, only names of leaf nodes may be repeated. Error will be thrown if names of intermediate nodes are repeated as there will be confusion. This error can be ignored by setting allow_duplicates to be True.

>>> from bigtree import list_to_tree_by_relation
>>> relations_list = [("a", "b"), ("a", "c"), ("b", "d"), ("b", "e"), ("c", "f"), ("e", "g"), ("e", "h")]
>>> root = list_to_tree_by_relation(relations_list)
>>> root.show()
a
β”œβ”€β”€ b
β”‚   β”œβ”€β”€ d
β”‚   └── e
β”‚       β”œβ”€β”€ g
β”‚       └── h
└── c
    └── f
Parameters:
  • relations (Iterable[Tuple[str, str]]) – list containing tuple containing parent-child names

  • allow_duplicates (bool) – allow duplicate intermediate nodes such that child node will be tagged to multiple parent nodes, defaults to False

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.nested_dict_to_tree(node_attrs: ~typing.Dict[str, ~typing.Any], name_key: str = 'name', child_key: str = 'children', node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ
Construct tree from nested recursive dictionary.
  • key: name_key, child_key, or any attributes key.

  • value of name_key (str): node name.

  • value of child_key (List[Dict[str, Any]]): list of dict containing name_key and child_key (recursive).

>>> from bigtree import nested_dict_to_tree
>>> path_dict = {
...     "name": "a",
...     "age": 90,
...     "children": [
...         {"name": "b",
...          "age": 65,
...          "children": [
...              {"name": "d", "age": 40},
...              {"name": "e", "age": 35, "children": [
...                  {"name": "g", "age": 10},
...              ]},
...          ]},
...     ],
... }
>>> root = nested_dict_to_tree(path_dict)
>>> root.show(attr_list=["age"])
a [age=90]
└── b [age=65]
    β”œβ”€β”€ d [age=40]
    └── e [age=35]
        └── g [age=10]
Parameters:
  • node_attrs (Dict[str, Any]) – dictionary containing node, children, and node attribute information, key: name_key and child_key value of name_key (str): node name value of child_key (List[Dict[str, Any]]): list of dict containing name_key and child_key (recursive)

  • name_key (str) – key of node name, value is type str

  • child_key (str) – key of child list, value is type list

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)

bigtree.tree.construct.str_to_tree(tree_string: str, tree_prefix_list: ~typing.List[str] = [], node_type: ~typing.Type[~bigtree.node.node.Node] = <class 'bigtree.node.node.Node'>) NodeΒΆ

Construct tree from tree string

>>> from bigtree import str_to_tree
>>> tree_str = 'a\nβ”œβ”€β”€ b\nβ”‚   β”œβ”€β”€ d\nβ”‚   └── e\nβ”‚       β”œβ”€β”€ g\nβ”‚       └── h\n└── c\n    └── f'
>>> root = str_to_tree(tree_str, tree_prefix_list=["β”œβ”€β”€", "└──"])
>>> root.show()
a
β”œβ”€β”€ b
β”‚   β”œβ”€β”€ d
β”‚   └── e
β”‚       β”œβ”€β”€ g
β”‚       └── h
└── c
    └── f
Parameters:
  • tree_string (str) – String to construct tree

  • tree_prefix_list (List[str]) – List of prefix to mark the end of tree branch/stem and start of node name, optional. If not specified, it will infer unicode characters and whitespace as prefix.

  • node_type (Type[Node]) – node type of tree to be created, defaults to Node

Returns:

(Node)