0

I can produce sorted bar plots by seaborn and pandas but I am having a hard time trying to do the same with matplotlib.pyplot, using matplotlib 3.3.4. Here is reproducible code to my problem, with the current output:

x = [5, 1, 3, 4, 2, 7, 6]
heights = [156, 151, 135, 107, 100,  86,  72]
x_string = [str(t) for t in x]


data = {
    'x': x.copy(),
    'heights': heights.copy()
    }
df = pd.DataFrame(data).sort_values('heights')
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(15,4))

ax1.bar(x='x', height='heights', data=df)
ax1.set_title('1) Using a DataFrame')

ax2.bar(x=x, height=heights)
ax2.set_title('2) Using Lists')

ax3.bar(x=x_string, height=heights)
ax3.set_title("3) With Strings")

fig.savefig('bar_order.png')
plt.show()

A possible workaround is to use something like

ax.bar(x=range(1, len(heights)+1), height=heights, tick_label=x)

Edit

The desired output is subplot 3. The behaviour I see, and I do not like, is that when I provide x as a list of integers, matplotlib takes it as the position on a normal mathematical x-axis but when I pass x as a list of string, matplotlib takes it as tick labels. Since bar charts are made for categorical variables, I expect the x argument to always be treated as labels, or maybe there should be a key to tell matplotlib if I want the x argument to be treated as labels or positions on the x-axis.

enter image description here

Ahmed Elashry
  • 389
  • 2
  • 12
  • You haven't shown what `x_string` is. When you say *"why it behaves like that"*, I think you mean *"why matplotlib, when given a string x-axis, first sorts the axis (in ASCII order)"*? And specifically you want to prevent that unwanted sort. (Or, is there a reason you don't just avoid string representation, at least for x?) – smci Jan 05 '22 at 21:04
  • Which version are you using? Make sure it's the latest. matplotlib used to also sort categorical axes by default, but that's been fixed, see [How do I get matplotlib to order bar-chart in the same order as my list?](https://stackoverflow.com/questions/48389751/how-do-i-get-matplotlib-to-order-bar-chart-in-the-same-order-as-my-list) – smci Jan 05 '22 at 21:11
  • First, thank you for your editing. The behaviour I see, and I do not like, is that when I provide `x` as a list of integers, matplotlib takes it as the position on _a normal mathematical x axis_ but when I pass x a list of string, matplotlib takes it as tick labels. – Ahmed Elashry Jan 05 '22 at 21:11
  • I am using `matplotlib 3.3.4`, and I think it doesn't sort alphabetically as seen in subplot 3. – Ahmed Elashry Jan 05 '22 at 21:14
  • 1
    Ok, but strictly is this a problem preventing you plotting (doesn't seem like it), or just a curiosity (*"Why does matplotlib treat list of string axes like that?"*) matplotlib has some quirks, suggest dig into its codebase and [github issues](https://github.com/matplotlib/matplotlib/issues) – smci Jan 05 '22 at 21:15
  • But is this a real problem, or just a curiosity? – smci Jan 05 '22 at 21:16
  • I am sorry if I wasn't clear. I updated the question to be more precise. It is not a problem as I already suggested a workaround but I want to know if there is a better more intuitive solution. – Ahmed Elashry Jan 05 '22 at 21:23
  • 1
    Your solution is the recommended way. It is just a different choice that matplotlib makes for bar plots vs plotting via pandas. Both choices have their pro and their contra. Matplotlib's approach is much easier to adapt, for example when using variable-width bars or when you explicitly want gaps (e.g. weekends). Matplotlib has a long history and a wide range of use cases. – JohanC Jan 05 '22 at 21:40
  • It seems I have to dig the source to understand why. Thank you for your comment! I will use my suggestion for now. – Ahmed Elashry Jan 06 '22 at 17:29

0 Answers0