8000 MNT: add a warning if a categroical string array is all convertible t… · matplotlib/matplotlib@24db221 · GitHub
[go: up one dir, main page]

Skip to content

Commit 24db221

Browse files
committed
MNT: add a warning if a categroical string array is all convertible to numbers or dates
1 parent 56243e9 commit 24db221

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

lib/matplotlib/category.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
"""
1313

1414
from collections import OrderedDict
15+
import dateutil.parser
1516
import itertools
1617

1718
import numpy as np
19+
import warnings
1820

21+
import matplotlib.cbook as cbook
1922
import matplotlib.units as units
2023
import matplotlib.ticker as ticker
2124

@@ -168,6 +171,20 @@ def __init__(self, data=None):
168171
if data is not None:
169172
self.update(data)
170173

174+
@staticmethod
175+
def _str_is_convertable(val):
176+
"""
177+
Helper method to see if string can be cast to float or parsed as date.
178+
"""
179+
try:
180+
float(val)
181+
except ValueError:
182+
try:
183+
dateutil.parser.parse(val)
184+
except ValueError:
185+
return False
186+
return True
187+
171188
def update(self, data):
172189
"""Maps new values to integer identifiers.
173190
@@ -183,11 +200,20 @@ def update(self, data):
183200
"""
184201
data = np.atleast_1d(np.array(data, dtype=object))
185202

203+
convertable = True
186204
for val in OrderedDict.fromkeys(data):
205+
# OrderedDict just iterates over unique values in data.
187206
if not isinstance(val, (str, bytes)):
188207
raise TypeError("{val!r} is not a string".format(val=val))
208+
# check if we can convert string to number or date...
209+
convertable = (convertable and self._str_is_convertable(val))
189210
if val not in self._mapping:
190211
self._mapping[val] = next(self._counter)
212+
if convertable:
213+
cbook._warn_external('using category units to plot a list of '
214+
'strings that is a;; floats or parsable as dates. '
215+
'If you do not mean these to be categories, cast '
216+
'to the approriate data type before plotting.')
191217

192218

193219
# Connects the convertor to matplotlib

lib/matplotlib/tests/test_category.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ class TestPlotNumlike(object):
203203
@pytest.mark.parametrize("ndata", numlike_data, ids=numlike_ids)
204204
def test_plot_numlike(self, ax, plotter, ndata):
205205
counts = np.array([4, 6, 5])
206-
plotter(ax, ndata, counts)
206+
with pytest.warns(UserWarning, match='using category units to plot'):
207+
plotter(ax, ndata, counts)
207208
axis_test(ax.xaxis, ndata)
208209

209210

@@ -261,12 +262,14 @@ def test_update_plot(self, ax, plotter):
261262

262263
PLOT_BROKEN_IDS = ["scatter", "plot", "bar"]
263264

265+
@pytest.mark.filterwarnings('ignore::UserWarning')
264266
@pytest.mark.parametrize("plotter", PLOT_BROKEN_LIST, ids=PLOT_BROKEN_IDS)
265267
@pytest.mark.parametrize("xdata", fvalues, ids=fids)
266268
def test_mixed_type_exception(self, ax, plotter, xdata):
267269
with pytest.raises(TypeError):
268270
plotter(ax, xdata, [1, 2])
269271

272+
@pytest.mark.filterwarnings('ignore::UserWarning')
270273
@pytest.mark.parametrize("plotter", PLOT_BROKEN_LIST, ids=PLOT_BROKEN_IDS)
271274
@pytest.mark.parametrize("xdata", fvalues, ids=fids)
272275
def test_mixed_type_update_exception(self, ax, plotter, xdata):

0 commit comments

Comments
 (0)
0