1212"""
1313
1414from collections import OrderedDict
15+ import dateutil .parser
1516import itertools
17+ import logging
1618
1719import numpy as np
1820
21+ import matplotlib .cbook as cbook
1922import matplotlib .units as units
2023import matplotlib .ticker as ticker
2124
2225
26+ _log = logging .getLogger (__name__ )
27+
28+
2329class StrCategoryConverter (units .ConversionInterface ):
2430 @staticmethod
2531 def convert (value , unit , axis ):
@@ -174,6 +180,21 @@ def __init__(self, data=None):
174180 if data is not None :
175181 self .update (data )
176182
183+ @staticmethod
184+ def _str_is_convertible (val ):
185+ """
186+ Helper method to see if a string can be cast to float or
187+ parsed as date.
188+ """
189+ try :
190+ float (val )
191+ except ValueError :
192+ try :
193+ dateutil .parser .parse (val )
194+ except ValueError :
195+ return False
196+ return True
197+
177198 def update (self , data ):
178199 """Maps new values to integer identifiers.
179200
@@ -189,11 +210,22 @@ def update(self, data):
189210 """
190211 data = np .atleast_1d (np .array (data , dtype = object ))
191212
213+ # check if convertable to number:
214+ convertable = True
192215 for val in OrderedDict .fromkeys (data ):
216+ # OrderedDict just iterates over unique values in data.
193217 if not isinstance (val , (str , bytes )):
194218 raise TypeError ("{val!r} is not a string" .format (val = val ))
219+ if convertable :
220+ # this will only be called so long as convertable is True.
221+ convertable = self ._str_is_convertible (val )
195222 if val not in self ._mapping :
196223 self ._mapping [val ] = next (self ._counter )
224+ if convertable :
225+ _log .info ('Using categorical units to plot a list of strings '
226+ 'that are all parsable as floats or dates. If these '
227+ 'strings should be plotted as numbers, cast to the '
228+ 'approriate data type before plotting.' )
197229
198230
199231# Register the converter with Matplotlib's unit framework
0 commit comments