繁体   English   中英

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/的图表

在此输入图像描述

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

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

即,水平分组条形图中的条形图被颠倒排列。

怎么解决?

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

每个组的顺序是错误的

我们可以看到订单也是非常规的,因为人们会期望图表是自上而下的,顶部是“AAA”,而不是底部。

如果您搜索“Excel颠倒”,您会发现人们在Excel中的所有地方都在抱怨这一点。 Microsoft Excel有一个修复它,Matplotlib / Panda / Searborn / Ploty /等有没有修复它?

我认为群组和子群的联合错误顺序归结为一个特征: y轴向上增加,就像在通常的情节中一样。 尝试反转轴的y轴,如同这个无熊猫的例子:

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数据帧。 例如:

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

在我看来,这是大熊猫功能中的一个错误。 至少用户应该能够传递一个像reverse_order = True等参数。

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

这只是一个正确的条形顺序,它被称为......,正确的顺序。 因此,任何不正确的订单都是错误的订单。 :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)

在此输入图像描述

一般修复很简单:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM