| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| """ | ||
| if unit is None: | ||
| raise ValueError( | ||
| 'Missing unit for StrCategoryConverter. This might be caused' |
There was a problem hiding this comment.
So what's missing here is the mapping from category to float. Worried about using unit in a user facing error because unit is a kwarg that doesn't have to be passed in for categoricals to work.
Sorry, something went wrong.
There was a problem hiding this comment.
Worried about using unit in a user facing error because unit is a kwarg that doesn't have to be passed in for categoricals to work.
That's why I'm casting the error message to "Failed to convert..." using raise ... from.
So what's missing here is the mapping from category to float.
Not sure what that means. Moving the example from pyplot to ax to make it a little more obvious:
ax = plt.gca() ax.bar([1, 2, 3], [50, 10, 20]) ax.set_xticks(['banana', 'apple', 'pear'])
We are trying to string positions (not labels) to a float axis. IMHO there's nothing missing here and this should error out. Ideally, the error message would be something like "Attemtping to set categorical ticks to a non-categorical axis".
But there's no good place to raise that.
The original stacktrace before this PR was:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-13c713392566> in <module>()
2 ax = plt.gca()
3 ax.bar([1, 2, 3], [50, 10, 20])
----> 4 ax.set_xticks(['banana', 'apple', 'pear'])
~/dev/matplotlib/lib/matplotlib/axes/_base.py in set_xticks(self, ticks, minor)
3303 Default is ``False``.
3304 """
-> 3305 ret = self.xaxis.set_ticks(ticks, minor=minor)
3306 self.stale = True
3307 return ret
~/dev/matplotlib/lib/matplotlib/axis.py in set_ticks(self, ticks, minor)
1686 """
1687 # XXX if the user changes units, the information will be lost here
-> 1688 ticks = self.convert_units(ticks)
1689 if len(ticks) > 1:
1690 xleft, xright = self.get_view_interval()
~/dev/matplotlib/lib/matplotlib/axis.py in convert_units(self, x)
1488 return x
1489
-> 1490 ret = self.converter.convert(x, self.units, self)
1491 return ret
1492
~/dev/matplotlib/lib/matplotlib/category.py in convert(value, unit, axis)
51
52 # force an update so it also does type checking
---> 53 unit.update(values)
54
55 str2idx = np.vectorize(unit._mapping.__getitem__,
AttributeError: 'NoneType' object has no attribute 'update'
So, you can raise
In that situation I decided to raise on 3. add add context information in 2. using the raise .. from.
Sorry, something went wrong.
There was a problem hiding this comment.
I'm not against the error, I worry that the specific word unit will lead users down a google rabbit hole that's misguided. Basically, there's an xunit/yunit kwarg:
https://matplotlib.org/gallery/units/bar_demo2.html#sphx-glr-gallery-units-bar-demo2-py
axs[1, 0].bar(cms, cms, bottom=bottom, width=width, xunits=inch, yunits=cm)So I worry an error message with the word unit might make users think the fix is to pass in something, when really the issue is that the axis input data is not a string so the axis is not registered as string units. I wonder if the following is enough:
'Axis does not support StrCategoryConvertor; axis data values must be strings'
Like you, I want to help people catch that the problem is the mismatch between the plot data and the tick data.
Sorry, something went wrong.
There was a problem hiding this comment.
Rephrased to
raise ValueError(
'Missing category information for StrCategoryConverter; '
'this might be caused by unintendedly mixing categorical and '
'numeric data')
I don't want to mention an Axis as we don't know the call context here. In the end, this is also why we can only guess the reason for the failure but not make a clear statement what to change.
Sorry, something went wrong.
| from matplotlib import cbook | ||
|
|
||
|
|
||
| class ConversionError(ValueError): |
There was a problem hiding this comment.
this is a bit bikesheddy but it looks more like a TypeError than a ValueError to me.
Sorry, something went wrong.
| if unit is None: | ||
| raise ValueError( | ||
| 'Missing unit for StrCategoryConverter. This might be caused' | ||
| 'by unintendedly mixing categorical and numeric data.') |
There was a problem hiding this comment.
Minor preference for error messages that are single sentence and without a final dot, as that's what we mostly have in the codebase (so replace the middle dot by a semicolon).
Also a missing space after "caused".
Sorry, something went wrong.
|
Travis CI failure is due to #13137 and unrelated to this PR. By me, this is ready to go in. |
Sorry, something went wrong.
| @staticmethod | ||
| def convert(value, unit, axis): | ||
| """Converts strings in value to floats using | ||
| """Convert strings in value to floats using |
There was a problem hiding this comment.
Just inherit the docstring from units.ConversionInterface perhaps? (and possibly edit that docstring).
Sorry, something went wrong.
There was a problem hiding this comment.
I don't think we can reasonably use an inherited docstring here. Using the conversion interface for string-index mapping is a bit of a stretch and justifies explicit description.
Sorry, something went wrong.
There was a problem hiding this comment.
sure
Sorry, something went wrong.
There was a problem hiding this comment.
anyone can merge (including tim) when ci passes.
Sorry, something went wrong.
|
Self-merging based on the reviews. The Travis CI failure is still due to #13137 (unrelated to this PR). |
Sorry, something went wrong.
|
Re-milestoned to 3.1 so we do not have to deal with backporting the f string and because there is a subtle API change (the type of the raise exception) in this. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
PR Summary
Fixes #12990. The call stack is a bit lengthy, but that's because the error happens several levels down and at least the reason gets clear.
Assigning categoricals to floats.
results in
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) ~/dev/matplotlib/lib/matplotlib/axis.py in convert_units(self, x) 1489 try: -> 1490 ret = self.converter.convert(x, self.units, self) 1491 except Exception as e: ~/dev/matplotlib/lib/matplotlib/category.py in convert(value, unit, axis) 45 raise ValueError( ---> 46 'Missing unit for StrCategoryConverter. This might be caused' 47 'by unintendedly mixing categorical and numeric data.') ValueError: Missing unit for StrCategoryConverter. This might be causedby unintendedly mixing categorical and numeric data. The above exception was the direct cause of the following exception: ConversionError Traceback (most recent call last) <ipython-input-2-8d8628e715b5> in <module>() 4 ticks = ['banana', 'apple', 'pear'] 5 plt.bar(xs, ys) ----> 6 plt.xticks(ticks) ~/dev/matplotlib/lib/matplotlib/pyplot.py in xticks(ticks, labels, **kwargs) 1518 labels = ax.get_xticklabels() 1519 elif labels is None: -> 1520 locs = ax.set_xticks(ticks) 1521 labels = ax.get_xticklabels() 1522 else: ~/dev/matplotlib/lib/matplotlib/axes/_base.py in set_xticks(self, ticks, minor) 3303 Default is ``False``. 3304 """ -> 3305 ret = self.xaxis.set_ticks(ticks, minor=minor) 3306 self.stale = True 3307 return ret ~/dev/matplotlib/lib/matplotlib/axis.py in set_ticks(self, ticks, minor) 1689 """ 1690 # XXX if the user changes units, the information will be lost here -> 1691 ticks = self.convert_units(ticks) 1692 if len(ticks) > 1: 1693 xleft, xright = self.get_view_interval() ~/dev/matplotlib/lib/matplotlib/axis.py in convert_units(self, x) 1491 except Exception as e: 1492 raise munits.ConversionError('Failed to convert value(s) to axis ' -> 1493 'units: %r' % x) from e 1494 return ret 1495 ConversionError: Failed to convert value(s) to axis units: ['banana', 'apple', 'pear']Assigning categoricals to dates.
results in
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) ~/dev/matplotlib/lib/matplotlib/axis.py in convert_units(self, x) 1489 try: -> 1490 ret = self.converter.convert(x, self.units, self) 1491 except Exception as e: ~/dev/matplotlib/lib/matplotlib/dates.py in convert(value, unit, axis) 1805 """ -> 1806 return date2num(value) 1807 ~/dev/matplotlib/lib/matplotlib/dates.py in date2num(d) 421 return d --> 422 return _to_ordinalf_np_vectorized(d) 423 ~/miniconda3/envs/mpl/lib/python3.6/site-packages/numpy/lib/function_base.py in __call__(self, *args, **kwargs) 2754 -> 2755 return self._vectorize_call(func=func, args=vargs) 2756 ~/miniconda3/envs/mpl/lib/python3.6/site-packages/numpy/lib/function_base.py in _vectorize_call(self, func, args) 2824 else: -> 2825 ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args) 2826 ~/miniconda3/envs/mpl/lib/python3.6/site-packages/numpy/lib/function_base.py in _get_ufunc_and_otypes(self, func, args) 2784 inputs = [arg.flat[0] for arg in args] -> 2785 outputs = func(*inputs) 2786 ~/dev/matplotlib/lib/matplotlib/dates.py in _to_ordinalf(dt) 225 --> 226 base = float(dt.toordinal()) 227 AttributeError: 'numpy.str_' object has no attribute 'toordinal' The above exception was the direct cause of the following exception: ConversionError Traceback (most recent call last) <ipython-input-3-e7444cbe73e7> in <module>() 4 ticks = ['banana', 'apple', 'pear'] 5 plt.bar(xs, ys) ----> 6 plt.xticks(ticks) ~/dev/matplotlib/lib/matplotlib/pyplot.py in xticks(ticks, labels, **kwargs) 1518 labels = ax.get_xticklabels() 1519 elif labels is None: -> 1520 locs = ax.set_xticks(ticks) 1521 labels = ax.get_xticklabels() 1522 else: ~/dev/matplotlib/lib/matplotlib/axes/_base.py in set_xticks(self, ticks, minor) 3303 Default is ``False``. 3304 """ -> 3305 ret = self.xaxis.set_ticks(ticks, minor=minor) 3306 self.stale = True 3307 return ret ~/dev/matplotlib/lib/matplotlib/axis.py in set_ticks(self, ticks, minor) 1689 """ 1690 # XXX if the user changes units, the information will be lost here -> 1691 ticks = self.convert_units(ticks) 1692 if len(ticks) > 1: 1693 xleft, xright = self.get_view_interval() ~/dev/matplotlib/lib/matplotlib/axis.py in convert_units(self, x) 1491 except Exception as e: 1492 raise munits.ConversionError('Failed to convert value(s) to axis ' -> 1493 'units: %r' % x) from e 1494 return ret 1495 ConversionError: Failed to convert value(s) to axis units: ['banana', 'apple', 'pear']