# Matplotlib, horizontal bar chart (barh) is upside-down

## Question:

**TL’DR**, the vertical bar charts are shown in a conventional way — things line up from left to right. However, when it is converted to horizontal bar chart (from `bar`

to `barh`

), everything is upside-down. I.e., for a grouped bar chart, not only the order of the grouped bar is wrong, the order of the each group is wrong as well.

For e.g., the graph from http://dwheelerau.com/2014/05/28/pandas-data-analysis-new-zealanders-and-their-sheep/

If you look closely, you will find that the the bar and legend are in reverse order — Beef shows on top in legend but on bottom in the graph.

As the simplest demo, I changed `kind='bar',`

to `kind='barh',`

from this graph

https://plot.ly/pandas/bar-charts/#pandas-grouped-bar-chart

and the result looks like this:

https://plot.ly/7/~xpt/

I.e., the bars in the horizontal grouped bar chart is ordered upside-down.

How to fix it?

**EDIT:** @Ajean, it is actually not only the order of the grouped bar is wrong, the order of the each group is wrong as well. The graph from Simple customization of matplotlib/pandas bar chart (labels, ticks, etc.) shows it clearly:

We can see that the order is unconventional too, because people would expect the graph to be top-down, with “AAA” at the top, not the bottom.

If you search for “Excel upside-down”, you will find people are complaining about this in Excel all over the places. The Microsoft Excel has a fix for it, do Matplotlib/Panda/Searborn/Ploty/etc has a fix for it?

## Answers:

I believe the joint wrong order of groups and subgroups boils down to a single feature: that the `y`

axis increases upwards, as in a usual plot. Try reversing the `y`

axis of your axes as in this pandas-less example:

```
import numpy as np
import matplotlib.pyplot as plt
x=range(5)
y=np.random.randn(5)
#plot1: bar
plt.figure()
plt.bar(x,y)
#plot2: barh, wrong order
plt.figure()
plt.barh(x,y)
#plot3: barh with correct order: top-down y axis
plt.figure()
plt.barh(x,y)
plt.gca().invert_yaxis()
```

Specifically for pandas, `pandas.DataFrame.plot`

and its various plotting submethods return a matplotlib axes object, so you can invert its y axis directly:

```
ax = df.plot.barh() # or df.plot(), or similar
ax.invert_yaxis()
```

I will consider this to be a bug, i.e., the y position of the bars are not assigned correctly. The patch is however relatively simple:

This is only one right order of bars, and that is called…, the right order. Anything that is not the right order, is thus a buggy order. :p

```
In [63]:
print df
Total_beef_cattle Total_dairy_cattle Total_sheep Total_deer
1994 0.000000 0.000000 0.000000 0.000000
2002 -11.025827 34.444950 -20.002034 33.858009
2003 -8.344764 32.882482 -20.041908 37.229441
2004 -11.895128 34.207998 -20.609926 42.707754
2005 -12.366101 32.506699 -19.379727 38.499840
Total_pigs Total_horses
1994 0.000000 0.000000
2002 -19.100637 11.811093
2003 -10.766476 18.504488
2004 -8.072078 13.376472
2005 -19.230733 -100.000000
In [64]:
ax = df.plot(kind='barh', sort_columns=True)
#Get the actual bars
bars = [item for item in ax.get_children() if isinstance(item, matplotlib.patches.Rectangle)]
bars = bars[:df.size]
#Reset the y positions for each bar
bars_y = [plt.getp(item, 'y') for item in bars]
for B, Y in zip(bars, np.flipud(np.array(bars_y).reshape(df.shape[::-1])).ravel()):
B.set_y(Y)
```

General fix is simple:

```
handles, labels = axis.get_legend_handles_labels()
# reverse to keep order consistent
axis.legend(reversed(handles), reversed(labels), loc='upper left')
```

I believe the simplest solution for this problem is to reverse the pandas dataframe before plotting. For example:

```
df = df.iloc[::-1]
df.plot.barh(stacked=True);
```

In my opinion that is a bug in the pandas barh function. At least users should be able to pass an argument like reverse_order = True etc.