Skip to content

Commit f672535

Browse files
committed
Add epsilon when summing floats
Fix #3
1 parent 687645c commit f672535

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

easyplotly/internals.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
import pandas as pd
44
import numpy as np
55

6+
"""When computing the sum of weights, we had an epsilon to make sure that the JS code
7+
will see a total larger than the sum. See #3. Note that the example reported at #3 is
8+
fixed already with EPS=1e-16. But, since (0.1+0.2-0.3)*10=5.5e-16, we prefer to take
9+
a larger value here."""
10+
EPS = 1e-15
11+
612

713
def tree_like_structure_to_dict(values):
814
"""Transform a series, a dict, or a collection of such objects, into a dictionary index by tuples"""
@@ -51,7 +57,12 @@ def sunburst_or_treemap(values, root_label=None, branchvalues='total', **kwargs)
5157

5258
if branchvalues == 'total' and not np.isnan(value):
5359
# Sum the descendent weights onto the parents (skip nans)
54-
tree[parent] += value
60+
if isinstance(value, int):
61+
tree[parent] += value
62+
else:
63+
# Make sure that the parent is going to be bigger
64+
# than the sum of values, even if we change the summation order (#3)
65+
tree[parent] += value * (1 + depth * EPS)
5566

5667
def ends_with_none_or_nan(key):
5768
if not key:

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ jupytext
66
nbconvert
77
jupyter_client
88
ipykernel
9+
mock
910

1011
# Examples
1112
world_bank_data

tests/test_sunburst.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import sys
22
import pytest
3+
4+
try:
5+
import unittest.mock as mock
6+
except ImportError:
7+
import mock
38
import pandas as pd
49
import plotly.graph_objects as go
510
from easyplotly import Sunburst
@@ -93,3 +98,16 @@ def test_sunburst_index_none_is_removed():
9398
def test_negative_raise_error():
9499
with pytest.raises(ValueError, match='Negative'):
95100
Sunburst({('A', 'a'): -5})
101+
102+
103+
def test_parent_value_strictly_larger():
104+
with mock.patch('easyplotly.internals.EPS', 0.01):
105+
sunburst_input = {('A', 'a', '1', 'i'): 1.0}
106+
sunburst_expected = go.Sunburst(
107+
ids=['/A/a/1/i', '/A/a/1', '/A/a', '/A'],
108+
labels=['i', '1', 'a', 'A'],
109+
parents=['/A/a/1', '/A/a', '/A', None],
110+
values=[1., 1.01, 1.02, 1.03],
111+
branchvalues='total'
112+
)
113+
assert Sunburst(sunburst_input) == sunburst_expected

0 commit comments

Comments
 (0)