Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fce534c

Browse files
authored
Merge pull request #19187 from CharlesHe16/master
ENH: Support callable for formatting of Sankey labels
2 parents 2631206 + 35954a0 commit fce534c

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
Support callable for formatting of Sankey labels
2+
------------------------------------------------
3+
4+
The `format` parameter of `matplotlib.sankey.Sankey` can now accept callables.
5+
6+
This allows the use of an arbitrary function to label flows, for example allowing
7+
the mapping of numbers to emoji.
8+
9+
.. plot::
10+
11+
import matplotlib.pyplot as plt
12+
from matplotlib.sankey import Sankey
13+
import math
14+
15+
16+
def display_in_cats(values, min_cats, max_cats):
17+
def display_in_cat_scale(value):
18+
max_value = max(values, key=abs)
19+
number_cats_to_show = \
20+
max(min_cats, math.floor(abs(value) / max_value * max_cats))
21+
return str(number_cats_to_show * '🐱')
22+
23+
return display_in_cat_scale
24+
25+
26+
flows = [35, 15, 40, -20, -15, -5, -40, -10]
27+
orientations = [-1, 1, 0, 1, 1, 1, -1, -1]
28+
29+
# Cats are good, we want a strictly positive number of them
30+
min_cats = 1
31+
# More than four cats might be too much for some people
32+
max_cats = 4
33+
34+
cats_format = display_in_cats(flows, min_cats, max_cats)
35+
36+
sankey = Sankey(flows=flows, orientations=orientations, format=cats_format,
37+
offset=.1, head_angle=180, shoulder=0, scale=.010)
38+
39+
diagrams = sankey.finish()
40+
41+
diagrams[0].texts[2].set_text('')
42+
43+
plt.title(f'Sankey flows measured in cats \n'
44+
f'🐱 = {max(flows, key=abs) / max_cats}')
45+
46+
plt.show()

lib/matplotlib/sankey.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ def __init__(self, ax=None, scale=1.0, unit='', format='%G', gap=0.25,
8383
unit : str
8484
The physical unit associated with the flow quantities. If *unit*
8585
is None, then none of the quantities are labeled.
86-
format : str
87-
A Python number formatting string to be used in labeling the flow
88-
as a quantity (i.e., a number times a unit, where the unit is
89-
given).
86+
format : str or callable
87+
A Python number formatting string or callable used to label the
88+
flows with their quantities (i.e., a number times a unit, where the
89+
unit is given). If a format string is given, the label will be
90+
``format % quantity``. If a callable is given, it will be called
91+
with ``quantity`` as an argument.
9092
gap : float
9193
Space between paths that break in/break away to/from the top or
9294
bottom.
@@ -739,7 +741,13 @@ def _get_angle(a, r):
739741
if label is None or angle is None:
740742
label = ''
741743
elif self.unit is not None:
742-
quantity = self.format % abs(number) + self.unit
744+
if isinstance(self.format, str):
745+
quantity = self.format % abs(number) + self.unit
746+
elif callable(self.format):
747+
quantity = self.format(number)
748+
else:
749+
raise TypeError(
750+
'format must be callable or a format string')
743751
if label != '':
744752
label += "\n"
745753
label += quantity

lib/matplotlib/tests/test_sankey.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,15 @@ def test_sankey():
1010
def test_label():
1111
s = Sankey(flows=[0.25], labels=['First'], orientations=[-1])
1212
assert s.diagrams[0].texts[0].get_text() == 'First\n0.25'
13+
14+
15+
def test_format_using_callable():
16+
# test using callable by slightly incrementing above label example
17+
18+
def show_three_decimal_places(value):
19+
return f'{value:.3f}'
20+
21+
s = Sankey(flows=[0.25], labels=['First'], orientations=[-1],
22+
format=show_three_decimal_places)
23+
24+
assert s.diagrams[0].texts[0].get_text() == 'First\n0.250'

0 commit comments

Comments
 (0)