【问题标题】:Matplotlib, horizontal bar chart (barh) is upside-downMatplotlib,水平条形图(barh)是倒置的
【发布时间】:2016-03-08 16:01:51
【问题描述】:

TL'DR,垂直条形图以传统方式显示——事物从左到右排列。但是,当它转换为水平条形图(从bar 到barh)时,一切都颠倒了。即,对于分组条形图,不仅分组条的顺序是错误的,而且每个组的顺序也是错误的。

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

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

作为最简单的demo,我把kind='bar',改成了kind='barh', 从这张图 https://plot.ly/pandas/bar-charts/#pandas-grouped-bar-chart 结果如下所示: https://plot.ly/7/~xpt/

即,水平分组条形图中的条形是倒置的。

如何解决?

编辑: @Ajean,实际上不仅分组条的顺序错误,每个组的顺序也错误。来自Simple customization of matplotlib/pandas bar chart (labels, ticks, etc.) 的图表清楚地表明了这一点:

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

如果您搜索“Excel 倒置”,您会发现到处都有人在 Excel 中抱怨这个问题。 Microsoft Excel 对其进行了修复,Matplotlib/Panda/Searborn/Ploty/etc 是否对其进行了修复?

【问题讨论】:

  • 您可以手动将条形手柄传递给plt.legend,然后随意订购。
  • 不,问题不在于传说,看看plot.ly/7/~xpt,A、B、C、D的顺序是正确的。是条顺序错误。
  • 嗯 .... 我不认为这是一个 bug 本身,而是一个约定问题。这些条通常按升序排列(即第一个元素是“0”,第二个元素是“1”,等等)。在此处展示的“自下而上”(“向上”表示“更高”)的案例中,第一个条形图位于每组的底部是有道理的。我认为,问题在于,传奇的约定是“自上而下”而不是“自下而上”。如果您真的想反转它,可能更改图例约定是最简单的。

标签: python pandas matplotlib bar-chart


【解决方案1】:

我相信组和子组的联合错误顺序归结为一个特征:y 轴向上增加,就像通常的情节一样。尝试反转坐标轴的 y 轴,如下面的 pandas-less 示例所示:

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,pandas.DataFrame.plot 及其各种绘图子方法返回一个 matplotlib 轴对象,因此您可以直接反转其 y 轴:

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

【讨论】:

  • 不,几乎不会。您最终将颠倒年份的顺序:1994-2012 到它的倒序。
  • @CTZhu 但这有点意思,不是吗?如果在bar 图中,1994->2012 从左到右,那么对于barh,可能需要从上到下的相同顺序。 OP 的编辑说“it is actually not only the order of the grouped bar is wrong, the order of the each group is wrong as well”向我建议这是一个有效的解决方案。如果他来告诉我不是,我会删除答案。
  • @AndrasDeak,是的,Andras,这正是我想要的。您能否也提供一个熊猫解决方案? This 是我自己能做到的。如果你愿意,你可以从那里开始。谢谢。
  • @xpt 1. 由于某种原因,您的要点不会为我加载。 2. 我没有安装 pandas,因此我的答案没有 pandas。 3. 我认为您应该能够使用相同的解决方案:plt.gca() 是轴,df.plot 也应该返回轴。所以你应该能够按照ax=df.plot(...); ax.invert_yaxis() 的方式做一些事情。你能确认一下吗?
  • 是的!非常感谢!在这里演示:gist.github.com/suntong/6572c4d339bdb98388a9
【解决方案2】:

我相信这个问题最简单的解决方案是在绘图之前反转 pandas 数据框。例如:

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

在我看来,这是 pandas barh 函数中的一个错误。至少用户应该能够传递诸如 reverse_order = True 等参数。

【讨论】:

    【解决方案3】:

    一般修复很简单:

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

    【讨论】:

      【解决方案4】:

      我认为这是一个错误,即条形的 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)
      

      【讨论】:

        猜你喜欢
        • 2016-07-14
        • 2012-03-26
        • 2013-05-15
        • 2017-11-21
        • 1970-01-01
        • 2012-09-26
        • 2021-11-08
        • 2019-03-01
        • 2016-10-13
        相关资源
        最近更新 更多