Here the problem is that I forgot the xs argument for plt.xticks:
plt.xticks(xs, ticks)
The error message should state so, but here's what it currently prints:
AttributeError: 'NoneType' object has no attribute 'update'
And the traceback:
------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-80-3ea0d1225cd3> in <module>
11 plt.bar(xs-width/2, neg_ys, width=width)
12 plt.bar(xs+width/2, pos_ys, width=width)
---> 13 plt.xticks(ticks)
/usr/local/lib/python3.6/dist-packages/matplotlib/pyplot.py in xticks(ticks, labels, **kwargs)
1547 labels = ax.get_xticklabels()
1548 elif labels is None:
-> 1549 locs = ax.set_xticks(ticks)
1550 labels = ax.get_xticklabels()
1551 else:
/usr/local/lib/python3.6/dist-packages/matplotlib/axes/_base.py in set_xticks(self, ticks, minor)
3335 Default is ``False``.
3336 """
-> 3337 ret = self.xaxis.set_ticks(ticks, minor=minor)
3338 self.stale = True
3339 return ret
/usr/local/lib/python3.6/dist-packages/matplotlib/axis.py in set_ticks(self, ticks, minor)
1702 """
1703 # XXX if the user changes units, the information will be lost here
-> 1704 ticks = self.convert_units(ticks)
1705 if len(ticks) > 1:
1706 xleft, xright = self.get_view_interval()
/usr/local/lib/python3.6/dist-packages/matplotlib/axis.py in convert_units(self, x)
1528 return x
1529
-> 1530 ret = self.converter.convert(x, self.units, self)
1531 return ret
1532
/usr/local/lib/python3.6/dist-packages/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'
For anyone who wants to work on this, note that it is legal to pass strings as positions to xticks(), in case the axis is categorical (e.g. bar(["foo", "bar"], [1, 2]); xticks(["foo"]))...
@anntzer is the categorial stuff explicitly supported for xticks/set_xticks? Neither pyplot.xticks nor Axes.set_xticks mention it and xticks(["a", "b"]) in your example messes up the label positions:
I think categorical support should be assumed unless a function explicitly says it doesn't support categoricals (for example neither plot() nor bar() mention they support categoricals either).
In the example you give, this is "expected": the categories "a" and "b" don't exist yet, so they get created at x = 2 and x = 3, to the right of "foo" and "bar".
@anntzer moved the discussion on categoricals to #12993. This is rather a fundamental question what plt.xticks(['a', 'b']) is supposed to do and thus beyond improving the error message for the given issue (even though the result of the discussion will affect how to properly handle this issue here).
Activity
anntzer commented on Dec 14, 2018
For anyone who wants to work on this, note that it is legal to pass strings as positions to xticks(), in case the axis is categorical (e.g. bar(["foo", "bar"], [1, 2]); xticks(["foo"]))...
timhoffm commented on Dec 15, 2018
@anntzer is the categorial stuff explicitly supported for xticks/set_xticks? Neither pyplot.xticks nor Axes.set_xticks mention it and xticks(["a", "b"]) in your example messes up the label positions:
anntzer commented on Dec 15, 2018
I think categorical support should be assumed unless a function explicitly says it doesn't support categoricals (for example neither plot() nor bar() mention they support categoricals either).
In the example you give, this is "expected": the categories "a" and "b" don't exist yet, so they get created at x = 2 and x = 3, to the right of "foo" and "bar".
timhoffm commented on Dec 15, 2018
@anntzer moved the discussion on categoricals to #12993. This is rather a fundamental question what plt.xticks(['a', 'b']) is supposed to do and thus beyond improving the error message for the given issue (even though the result of the discussion will affect how to properly handle this issue here).