如何控制在matplotlib 2.1.0 barh图表中显示条的顺序?

时间:2018-07-19 00:09:39

标签: python matplotlib

我正在使用matplotlib 2.1.0来显示水平条形图。我已经按值对数据进行了排序,但是matplotlib会按照标签的字母顺序显示条形图。

fig, [ax1,ax2] = plt.subplots(nrows=1,ncols=2, figsize = (8,3))
probs = [ 0.748, 0.052, 0.0376, 0.022, 0.017 ]
names = [ 'hibiscus', 'petunia', 'iris', 'rose', 'hyacinth' ]
ax1.barh( names, probs )

结果大致如下(抱歉,我无法粘贴图像):

    rose - **
 petunia - *****
    iris - ***
hyacinth - *
hibiscus - ************************************

如您所见,这些条以字母(或反向字母)顺序显示。我希望它们以列表顺序显示:

hibiscus - ************************************
 petunia - *****
    iris - ***
    rose - **
hyacinth - *

我在SO上发现了一个相关问题(我现在失去了链接),这表明这是较旧版本的matplotlib的问题。这是建议的解决方案:

ax1.barh( range(len(names)), probs )
ax1.set_yticks( range(len(names)), names )

此方法以正确的顺序或至少以相反的顺序显示数据。但是它不显示文本标签。相反,matplotlib通过索引标记条形,并完全忽略名称。

       4 - *
       3 - **
       2 - ***
       1 - *****
       0 - ************************************

我无法控制所使用的matplotlib的版本,因此我正在寻找一种方法来告诉matplotlib以标签名称的正确顺序显示数据。

我也发现了这个问题:How to determine the order of bars in a matplotlib bar chart。该解决方案使用的是熊猫DataFrame。我没有使用熊猫,只是为了说服matplotlib表现良好,将数据转换为DataFrame似乎有些过头。

如何控制matplotlib显示条形的顺序?


附录

该问题被标记为与我未参考的其他相关问题的重复:Pyplot sorting y-values automatically。区别是细微的,但是在调用barh()的两种方式之间有重要的区别。此问题中的代码首先使用对subplots()的调用的返回值,如下所示:

fig, [ax1,ax2] = plt.subplots(...)
ax1.barh(...)

另一个问题中的代码使用不同的接口:

plot.subplot(...)
plot.barh(...)

我不知道为什么它们应该以不同的方式工作,但是它们确实可以。具体来说,另一个问题(下面引用)的答案不适用于该问题中的代码。

plt.barh(range(len(w)),n)
plt.yticks(range(len(w)),w)

所以我尝试了该解决方案,但失败了。

ax1.barh(range(len(names)),probs)
 ### this next call generated a runtime error because ax1 has no method yticks()
ax1.yticks(range(len(names)),names)

但是,我发现有一个看似相似的通话,所以我尝试了:

ax1.barh( range(len(names)), probs )
ax1.set_yticks( range(len(names)), names )

正如我在原始帖子中所讨论的那样,这种方法从数字索引值生成了轴标签,而忽略了名称字符串。

最后一点:评论中提供了该问题的实际答案。我希望解开这个问题,以便Lorren或我可以为将来遇到此问题的任何人写一个正式答案。

1 个答案:

答案 0 :(得分:0)

感谢@LorranSutter,他给了我必要的提示来回答这个问题。

ax1.barh( range(len(names)), probs )
ax1.set_yticks( range(len(names))  )
ax1.set_yticklabels( names )