0

I want to force a bar chart to have the x-axis in a certain order. But for some reason it always orders it alphabetically, I don't know why. Is there a setting I can use to keep it from doing that.

In the example below, I want the x-axis ordered as ['d', 'a', 'c', 'b']. But it always orders it to ['a', 'b', 'c', 'd'].

Code:

import pandas as pd
import matplotlib.pyplot as plt

ser = pd.Series([1,2,3,4], index=['d', 'a', 'c', 'b'])
fig = plt.bar(ser.index, ser.values, tick_label=ser.index)

Screenshot:

enter image description here

Plasty Grove
  • 2,807
  • 5
  • 31
  • 42
  • 2
    The implementation of categorical plots had some hiccups like the one you describe. `matplotlib` v2.2.0 doesn't show this behaviour any more. So, if you can, update to the latest version and your problem (and others) is gone. – Mr. T Apr 08 '18 at 06:10
  • Thanks! Yea can confirm that it works as expected in v2.2.0. which is a relief. The workaround is really counter intuitive. – Plasty Grove Apr 08 '18 at 07:04
  • I would not call that counter-intuitive. After all it is the same strategy you would use when drawing those bars on a sheet of paper. Or do you have a ruler which has letters instead of numbers on it? – ImportanceOfBeingErnest Apr 08 '18 at 21:36
  • @ImportanceOfBeingErnest - I have minimal plotting experience, so maybe it is counter-intuitive to me. I just assumed that since python lists are ordered, a bar chart should just show the values in the same order. If I wanted them ordered, I could have done so by myself before passing it to the matplotlib. I don't always use bar graphs with numbers, sometimes I use arbitrary labels depending on my purpose. – Plasty Grove Apr 14 '18 at 04:28
  • Sure, you were just unlucky to hit the one version of matplotlib that shows this issue. In previous versions, you were not allowed to supply lists of strings at all (in which case it is intuitive to use numbers instead) and in the newest version the order of strings is preserved as expected. – ImportanceOfBeingErnest Apr 15 '18 at 09:20
  • Ah, I didn't know that it was a new feature. Makes sense now, thanks :). – Plasty Grove Apr 15 '18 at 23:29

1 Answers1

1

plt.bar() treats its first parameter as an array of X coordinates. Consider passing an integer array instead of a character array:

plt.bar(range(ser.shape[0]), ser.values, tick_label=ser.index)

enter image description here

DYZ
  • 55,249
  • 10
  • 64
  • 93