关于python:Matplotlib,水平条形图(barh)上下颠倒

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

TL'DR,垂直条形图以常规方式显示-东西从左到右排列。但是,将其转换为水平条形图(从barbarh)时,一切都是颠倒的。即,对于分组的条形图,不仅分组的条形的顺序是错误的,而且每个组的顺序也是错误的。

例如,该图来自http://dwheelerau.com/2014/05/28/pandas-data-analysis-new-zealanders-and-their-sheep/

enter image description here

如果仔细观察,会发现条和图例的顺序相反-牛肉在图例的顶部显示,但在图形的底部显示。

作为最简单的演示,我将kind='bar',更改为kind='barh',
从这张图
https://plot.ly/pandas/bar-charts/#pandas-grouped-bar-chart
结果看起来像这样:
https://plot.ly/7/~xpt/

也就是说,水平分组条形图中的条形颠倒排列。

如何解决?

编辑:@Ajean,实际上不仅是分组条的顺序是错误的,而且每个组的顺序也是错误的。 matplotlib / pandas条形图的简单定制中的图形(标签,刻度等)清楚地显示了它:

the order of the each group is wrong

我们可以看到顺序也是非常规的,因为人们希望图形是自上而下的," AAA"在顶部,而不是底部。

如果您搜索" Excel上下颠倒",您会发现人们在各地抱怨着Excel。 Microsoft Excel有一个修复程序,Matplotlib / Panda / Searborn / Ploty / etc是否有修复程序?


我相信组和子组的联合错误顺序归结为一个特征:y轴像通常的图一样向上增加。尝试反转轴的y轴,如以下无熊猫示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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()

专门针对大熊猫,pandas.DataFrame.plot及其各种绘图子方法返回一个matplotlib axes对象,因此您可以直接反转其y轴:

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


我认为解决此问题的最简单方法是在绘制之前反转熊猫数据框。例如:

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

我认为这是熊猫barh功能中的错误。至少用户应该能够传递类似reverse_order = True等的参数。


我会认为这是一个错误,即条的y位置分配不正确。但是,补丁相对简单:

这只是条的正确顺序,也就是...,正确的顺序。因此,任何不正确的命令都是错误的命令。 :p

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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)

enter image description here


常规修复很简单:

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