Repository navigation
Description
Bug report
Bug summary
plt.bar() only accept 1D arrays, and does not accept 2D arrays with a dimension that has length 1. E.g., does not accept arrays with shape (3,1). Unfortunately, the traceback is unhelpful.
Code for reproduction
from matplotlib import pyplot as plt
import numpy as np
plt.bar(np.zeros((2,)),np.zeros((2,1)))Actual outcome
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/pyplot.py", line 2648, in bar
ret = ax.bar(*args, **kwargs)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/__init__.py", line 1717, in inner
return func(ax, *args, **kwargs)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 2087, in bar
label='_nolegend_',
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/patches.py", line 659, in __init__
Patch.__init__(self, **kwargs)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/patches.py", line 103, in __init__
self.set_linewidth(linewidth)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/patches.py", line 351, in set_linewidth
self._linewidth = float(w)
TypeError: only length-1 arrays can be converted to Python scalars
Expected outcome
plt.bar() should be able to figure out that a 1D vector and a 2D array with a singleton dimension are equivalent. This can be done by applying squeeze if necessary. In any case if plt.bar() is going to fail unintuitively on this, it should test to see if the input is a 2D array, and provide an informative error message.
Matplotlib version
- Operating system: windows, linux, and mac
- Matplotlib version: most recent
- Matplotlib backend (
print(matplotlib.get_backend())): - Python version: 2.7 and 3.6
- Jupyter version (if applicable):
- Other libraries:
This code works with matplotlib version 1.4.2 and does not work with 2.1.1. Other pyplot functions do not exhibit this behavior. E.g., plt.plot(np.zeros((2,1)),np.zeros((2,1))) works fine.
Activity
jklymak commentedon Mar 9, 2018
ping @anntzer You last touched the logic for linewidth here:
matplotlib/lib/matplotlib/axes/_axes.py
Line 2221 in fbcfe76
@bringingheavendown I don't know that we can catch every input and give nice error messages, but I agree that there is no good reason for
barto be more persnickety thanplot...anntzer commentedon Mar 9, 2018
Actually I think that came in with @tacaswell's #9110 which added broadcasting to linewidths, which is apparently(?) unneeded (it's handled below with itertools.cycle(np.atleast_1d(linewidths))).
HoniSanders commentedon Mar 19, 2018
More info on comparing behavior of plt.plot() to plt.bar()
I.e., plt.plot() treats rows of the inputs as different readings from a single line, and columns as different lines. Therefore, it treats a single-column 2D array the same as a 1D vector.
plt.bar() seems to be missing the functionality of creating a grouped bar chart if passed multi-column data, as would be analogous to plt.plot(), see #10610
In any case, the key line in plt.plot() is line 658 of https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/lines.py
self._xy = np.column_stack(np.broadcast_arrays(x, y)).astype(float)efiring commentedon Mar 20, 2018
Moving grouped-bar support from hist to bar (#10610) seems like the right way to solve this. At present, bar specifies 1-D inputs. I'm leery of putting
squeezecalls all over the place; I would rather leave it to the user to provide inputs with the appropriate dimensions.HoniSanders commentedon Mar 20, 2018
Ok, but there should at least be a reasonable error message if plt.bar() is going to have unintuitive and undocumented requirements on its inputs.
jklymak commentedon Mar 20, 2018
We don't always add strict argument checking. We added some recently, but that was for a case where the error didn't trigger until
draw()was called.In this case, its pretty clear that a call to
baris causing an error inbardue to bad argument sizes. So I don't think this is as striong a case, and I'm 50/50 on whether it needs an argument check. But if someone wanted to put in a PR that did this in a way that didn't break other things and wasn't a lot of extra messy code, I think that would have a decent chance of being accepted.efiring commentedon Mar 20, 2018
The requirement is documented: "scalar or sequence of scalars" means no more than 1-D.
https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.bar.html#matplotlib-axes-axes-bar
xapple commentedon Jun 19, 2019
I had this error on a python installation that had
matplotlibversion3.1.0I was able to solve the problem by executing the following command:
It seems like this was fixed but then a regression was introduced.
github-actions commentedon Oct 9, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!