Skip to content

Commit

Permalink
Merge pull request #226 from kayjan/fix-zero-null-check
Browse files Browse the repository at this point in the history
fix: null checks to ignore zero values
  • Loading branch information
kayjan authored Apr 23, 2024
2 parents 34b6cb9 + 2fd08b6 commit f012007
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 4 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.17.2] - 2024-04-24
### Changed:
- DAG Constructor: `list_to_dag` and `dict_to_dag` does not rely on `dataframe_to_dag` as pandas dataframe operation
is phased out.
### Fixed:
- DAG Constructor: Handle cases where reserved keywords are part of attribute upon creation and throw error accordingly.
- [#224] Tree/DAG Constructor: Null checks to not interpret 0 as null, this affects `dataframe_to_tree_by_relation`,
`add_dataframe_to_tree_by_path`, `add_dataframe_to_tree_by_name`, `dataframe_to_tree`, and `dataframe_to_dag`.
This will also affect showing/printing of trees when `attr_omit_null` is set to True.

## [0.17.1] - 2024-04-23
### Fixed
Expand Down Expand Up @@ -550,7 +555,8 @@ ignore null attribute columns.
- Utility Iterator: Tree traversal methods.
- Workflow To Do App: Tree use case with to-do list implementation.

[Unreleased]: https://github.com/kayjan/bigtree/compare/0.17.1...HEAD
[Unreleased]: https://github.com/kayjan/bigtree/compare/0.17.2...HEAD
[0.17.2]: https://github.com/kayjan/bigtree/compare/0.17.1...0.17.2
[0.17.1]: https://github.com/kayjan/bigtree/compare/0.17.0...0.17.1
[0.17.0]: https://github.com/kayjan/bigtree/compare/0.16.4...0.17.0
[0.16.4]: https://github.com/kayjan/bigtree/compare/0.16.3...0.16.4
Expand Down
2 changes: 1 addition & 1 deletion bigtree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.17.1"
__version__ = "0.17.2"

from bigtree.binarytree.construct import list_to_binarytree
from bigtree.dag.construct import dataframe_to_dag, dict_to_dag, list_to_dag
Expand Down
2 changes: 1 addition & 1 deletion bigtree/utils/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def isnull(value: Any) -> bool:
"""
import math

if not value or (isinstance(value, float) and math.isnan(value)):
if value is None or (isinstance(value, float) and math.isnan(value)):
return True
return False

Expand Down
36 changes: 36 additions & 0 deletions tests/dag/test_construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,42 @@ def test_dataframe_to_dag_reverse():
assert_dag_structure_root(dag)
assert_dag_structure_root_attr(dag)

@staticmethod
def test_dataframe_to_dag_zero_attribute():
from bigtree.utils.iterators import dag_iterator

data = pd.DataFrame(
[
["a", None, 0],
["b", None, None],
["c", "a", -1],
["c", "b", -1],
["d", "a", 40],
["d", "c", 40],
["e", "d", 35],
["f", "c", 38],
["f", "d", 38],
["g", "c", 10],
["h", "g", 6],
],
columns=["child", "parent", "value"],
)
dag = dataframe_to_dag(data)
assert_dag_structure_root(dag)
for parent, _ in dag_iterator(dag):
match parent.name:
case "a":
assert hasattr(
parent, "value"
), "Check a attribute, expected value attribute"
assert parent.value == 0, "Check a value, expected 0"
case "b":
assert not hasattr(
parent, "value"
), "Check b attribute, expected no value attribute"
case "c":
assert parent.value == -1, "Check c value, expected -1"

def test_dataframe_to_dag_empty_row_error(self):
with pytest.raises(ValueError) as exc_info:
dataframe_to_dag(pd.DataFrame(columns=["child", "parent", "age"]))
Expand Down
101 changes: 101 additions & 0 deletions tests/tree/test_construct.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,32 @@ def test_add_dataframe_to_tree_by_path_col_name(self):
assert_tree_structure_node_root(self.root)

def test_add_dataframe_to_tree_by_path_col_name_reverse(self):
data = pd.DataFrame(
[
["a", 0],
["a/b", None],
["a/c", -1],
["a/b/d", 40],
["a/b/e", 35],
["a/c/f", 38],
["a/b/e/g", 10],
["a/b/e/h", 6],
],
columns=["PATH", "value"],
)
add_dataframe_to_tree_by_path(self.root, data)
assert_tree_structure_basenode_root(self.root)
assert_tree_structure_node_root(self.root)
assert hasattr(
self.root, "value"
), "Check root attribute, expected value attribute"
assert self.root.value == 0, "Check root value, expected 0"
assert not hasattr(
self.root["b"], "value"
), "Check b attribute, expected no value attribute"
assert self.root["c"].value == -1, "Check c value, expected -1"

def test_add_dataframe_to_tree_by_path_zero_attribute(self):
add_dataframe_to_tree_by_path(
self.root,
self.data[["age", "PATH"]],
Expand Down Expand Up @@ -1025,6 +1051,32 @@ def test_add_dataframe_to_tree_by_name_col_name_reverse(self):
assert_tree_structure_basenode_root_attr(self.root)
assert_tree_structure_node_root(self.root)

def test_add_dataframe_to_tree_by_name_zero_attribute(self):
data = pd.DataFrame(
[
["a", 0],
["b", None],
["c", -1],
["d", 40],
["e", 35],
["f", 38],
["g", 10],
["h", 6],
],
columns=["NAME", "value"],
)
add_dataframe_to_tree_by_name(self.root, data)
assert_tree_structure_basenode_root(self.root)
assert_tree_structure_node_root(self.root)
assert hasattr(
self.root, "value"
), "Check root attribute, expected value attribute"
assert self.root.value == 0, "Check root value, expected 0"
assert not hasattr(
self.root["b"], "value"
), "Check b attribute, expected no value attribute"
assert self.root["c"].value == -1, "Check c value, expected -1"

def test_add_dataframe_to_tree_by_name_empty_error(self):
with pytest.raises(ValueError) as exc_info:
add_dataframe_to_tree_by_name(self.root, pd.DataFrame())
Expand Down Expand Up @@ -2075,6 +2127,30 @@ def test_dataframe_to_tree_no_attribute():
root = dataframe_to_tree(path_data)
assert_tree_structure_basenode_root(root)

@staticmethod
def test_dataframe_to_tree_zero_attribute():
path_data = pd.DataFrame(
[
["a", 0],
["a/b", None],
["a/c", -1],
["a/b/d", 1],
["a/b/e", 1],
["a/c/f", 1],
["a/b/e/g", 1],
["a/b/e/h", 1],
],
columns=["PATH", "value"],
)
root = dataframe_to_tree(path_data)
assert_tree_structure_basenode_root(root)
assert hasattr(root, "value"), "Check root attribute, expected value attribute"
assert root.value == 0, "Check root value, expected 0"
assert not hasattr(
root["b"], "value"
), "Check b attribute, expected no value attribute"
assert root["c"].value == -1, "Check c value, expected -1"

@staticmethod
def test_dataframe_to_tree_empty_row_error():
path_data = pd.DataFrame(columns=["PATH", "age"])
Expand Down Expand Up @@ -2427,6 +2503,31 @@ def test_dataframe_to_tree_by_relation_col_name_reverse(self):
assert_tree_structure_basenode_root_attr(root)
assert_tree_structure_node_root(root)

@staticmethod
def test_dataframe_to_tree_by_relation_zero_attribute():
relation_data = pd.DataFrame(
[
["a", None, 0],
["b", "a", None],
["c", "a", -1],
["d", "b", 40],
["e", "b", 35],
["f", "c", 38],
["g", "e", 10],
["h", "e", 6],
],
columns=["child", "parent", "value"],
)
root = dataframe_to_tree_by_relation(relation_data)
assert_tree_structure_basenode_root(root)
assert_tree_structure_node_root(root)
assert hasattr(root, "value"), "Check root attribute, expected value attribute"
assert root.value == 0, "Check root value, expected 0"
assert not hasattr(
root["b"], "value"
), "Check b attribute, expected no value attribute"
assert root["c"].value == -1, "Check c value, expected -1"

@staticmethod
def test_dataframe_to_tree_by_relation_empty_row_error():
relation_data = pd.DataFrame(columns=["child", "parent"])
Expand Down
2 changes: 1 addition & 1 deletion tests/tree/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def test_print_tree_attr_omit_null_true(tree_node_negative_null_attr):
"│ └── e\n"
"│ ├── g [age=10]\n"
"│ └── h\n"
"└── c\n"
"└── c [age=0]\n"
" └── f\n"
)
assert_print_statement(
Expand Down

0 comments on commit f012007

Please sign in to comment.