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

Skip to content

Commit b184842

Browse files
story645tacaswell
authored andcommitted
Basic support for plotting lists of strings/categorical data. Support for updating ticks/animation in progress/buggy, 'especially for scatter.
1 parent 94f2fb8 commit b184842

10 files changed

Lines changed: 350 additions & 560 deletions

File tree

lib/matplotlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ def _jupyter_nbextension_paths():
14891489
'matplotlib.tests.test_backend_svg',
14901490
'matplotlib.tests.test_basic',
14911491
'matplotlib.tests.test_bbox_tight',
1492+
'matplotlib.tests.test_category',
14921493
'matplotlib.tests.test_cbook',
14931494
'matplotlib.tests.test_coding_standards',
14941495
'matplotlib.tests.test_collections',

lib/matplotlib/axes/_axes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import matplotlib.collections as mcoll
2222
import matplotlib.colors as mcolors
2323
import matplotlib.contour as mcontour
24+
import matplotlib.category as _ # <-registers a date unit converter
2425
import matplotlib.dates as _ # <-registers a date unit converter
2526
from matplotlib import docstring
2627
import matplotlib.image as mimage

lib/matplotlib/axis.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ def __init__(self, axes, pickradius=15):
662662
self.offsetText = self._get_offset_text()
663663
self.majorTicks = []
664664
self.minorTicks = []
665+
self.unit_data = []
665666
self.pickradius = pickradius
666667

667668
# Initialize here for testing; later add API
@@ -712,6 +713,17 @@ def _set_scale(self, value, **kwargs):
712713
def limit_range_for_scale(self, vmin, vmax):
713714
return self._scale.limit_range_for_scale(vmin, vmax, self.get_minpos())
714715

716+
@property
717+
def unit_data(self):
718+
"""Holds data that a ConversionInterface subclass relys on
719+
to convert between labels and indexes
720+
"""
721+
return self._unit_data
722+
723+
@unit_data.setter
724+
def unit_data(self, data):
725+
self._unit_data = data
726+
715727
def get_children(self):
716728
children = [self.label, self.offsetText]
717729
majorticks = self.get_major_ticks()

lib/matplotlib/category.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
catch all for categorical functions
3+
"""
4+
from __future__ import (absolute_import, division, print_function,
5+
unicode_literals)
6+
7+
import six
8+
import numpy as np
9+
10+
import matplotlib.units as units
11+
import matplotlib.ticker as ticker
12+
13+
14+
class StrCategoryConverter(units.ConversionInterface):
15+
@staticmethod
16+
def convert(value, unit, axis):
17+
"""Uses axis.unit_data map to encode
18+
data as integers
19+
"""
20+
21+
if isinstance(value, six.string_types):
22+
return dict(axis.unit_data)[value]
23+
24+
vals = np.asarray(value, dtype='str')
25+
for label, loc in axis.unit_data:
26+
vals[vals == label] = loc
27+
return vals.astype('float')
28+
29+
@staticmethod
30+
def axisinfo(unit, axis):
31+
seq, locs = zip(*axis.unit_data)
32+
majloc = StrCategoryLocator(locs)
33+
majfmt = StrCategoryFormatter(seq)
34+
return units.AxisInfo(majloc=majloc, majfmt=majfmt)
35+
36+
@staticmethod
37+
def default_units(data, axis):
38+
# the conversion call stack is:
39+
# default_units->axis_info->convert
40+
axis.unit_data = map_categories(data, axis.unit_data)
41+
return None
42+
43+
44+
def map_categories(data, old_map=[], sort=True):
45+
"""Create mapping between unique categorical
46+
values and numerical identifier.
47+
48+
Paramters
49+
---------
50+
data: iterable
51+
sequence of values
52+
old_map: list of tuple, optional
53+
if not `None`, than old_mapping will be updated with new values and
54+
previous mappings will remain unchanged)
55+
sort: bool, optional
56+
sort keys by ASCII value
57+
58+
Returns
59+
-------
60+
list of tuple
61+
[(label, ticklocation),...]
62+
63+
"""
64+
65+
# code typical missing data in the negative range because
66+
# everything else will always have positive encoding
67+
# question able if it even makes sense
68+
spdict = {'nan': -1, 'inf': -2, '-inf': -3}
69+
70+
# cast all data to str
71+
strdata = [str(d) for d in data]
72+
73+
uniq = set(strdata)
74+
75+
category_map = old_map.copy()
76+
77+
if old_map:
78+
olabs, okeys = zip(*old_map)
79+
olabs, okeys = set(olabs), set(okeys)
80+
svalue = max(okeys) + 1
81+
else:
82+
olabs, okeys = set(), set()
83+
svalue = 0
84+
85+
new_labs = (uniq - olabs)
86+
87+
missing = (new_labs & set(spdict.keys()))
88+
category_map.extend([(m, spdict[m]) for m in missing])
89+
90+
new_labs = (new_labs - missing)
91+
if sort:
92+
new_labs = list(new_labs)
93+
new_labs.sort()
94+
95+
new_locs = range(svalue, svalue + len(new_labs))
96+
category_map.extend(list(zip(new_labs, new_locs)))
97+
return category_map
98+
99+
100+
class StrCategoryLocator(ticker.FixedLocator):
101+
def __init__(self, locs):
102+
super(StrCategoryLocator, self).__init__(locs, None)
103+
104+
105+
class StrCategoryFormatter(ticker.FixedFormatter):
106+
def __init__(self, seq):
107+
super(StrCategoryFormatter, self).__init__(seq)
108+
109+
110+
# Connects the convertor to matplotlib
111+
units.registry[bytearray] = StrCategoryConverter()
112+
units.registry[str] = StrCategoryConverter()
113+
114+
if six.PY3:
115+
units.registry[bytes] = StrCategoryConverter()
116+
elif six.PY2:
117+
units.registry[unicode] = StrCategoryConverter()
-5.71 KB
Binary file not shown.
-19.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)