【问题标题】:Horizontal bar plot with multiple bars per ytick每个 ytick 有多个条形的水平条形图
【发布时间】:2019-04-06 23:48:12
【问题描述】:

我不太了解您应该如何传递参数以在 matplotlib 中创建水平条形图。我只是想模仿我在此示例代码中看到的内容...https://pythonspot.com/matplotlib-bar-chart/

以及我在此 stackoverflow 帖子中看到的内容 How to plot multiple horizontal bars in one chart with matplotlib

现在我的代码如下:

import numpy as np
x_locs = np.arange(len(total_vals))
t_label_lst = ['Digital Learning Apps', 'News, Events, Daily', 'News on School Events', 'STEM Extracurriculars & School Programs', 'Hiring, STEM Workforce', 'Women in STEM', 'Activities and Projects Outside of the Classroom', 'Ambiguous', 'Ambiguous, STEM in College', 'Next Generation of Engineers', 'News, Events, Daily', 'Educational Policy and Higher Education, Reform', 'STEM Activities, Building, Arts, and Design', 'Engaging students with STEM using programming and robotics', 'Black Leaders in STEM', 'Next Generation of Engineers', 'Ambiguous', 'Astronomy, NASA', 'STEM workshops and summer camps', 'Competitions, Team Credit', 'Ambiguous, Technology Hashtags', 'Google Education', 'Good Job Today! Crediting Daily Activities and Work', 'Engaging students with STEM using programming and robotics', 'Environmental Science', 'Teachers, Public Schools In STEM', 'Ambiguous', 'Edtech Companies', 'Ambiguous, PHD Conversation', 'Ambiguous', 'Engaging students with STEM using programming and robotics', 'Ambiguous, Virtual Reality and Personalized learning mention', 'Ambiguous', 'Ambiguous', 'Ambiguous, #Autism hashtag has disproportionate weight']

print(x_locs)
total_vals = [23668, 13186, 10752, 10002, 9558, 9126, 8138, 7389, 7006, 6965, 6859, 6621, 6538, 5700, 5110, 5069, 4419, 4025, 3943, 3866, 3761, 3697, 3543, 3294, 3067, 2928, 2511, 2491, 2353, 2312, 2229, 2175, 2021, 1921, 1787]
positive_vals = [9941, 9306, 7595, 5935, 5913, 7488, 5258, 4905, 4026, 5242, 5557, 3225, 3530, 3055, 3300, 3503, 2461, 2199, 2074, 2379, 1665, 2274, 2250, 1674, 1523, 1533, 1241, 859, 1504, 1419, 1132, 1082, 805, 753, 580]
neutral_vals = [13727, 3880, 3157, 4067, 3645, 1638, 2880, 2484, 2980, 1723, 1302, 3396, 3008, 2645, 1810, 1566, 1958, 1826, 1869, 1487, 2096, 1423, 1293, 1620, 1544, 1395, 1270, 1632, 849, 893, 1097, 1093, 1216, 1168, 1207]

rects1 = ax.barh(x_locs, total_vals, width=.15, color='r', label="total tweet count")
# rects2 = ax.barh(positive_vals, width=.2, color = 'b', label="positive tweet count")
# rects3 = ax.barh(neutral_vals, width=.2, color='yellow', label="neutral tweet count")
ax.set(yticks=x_locs, yticklabels=t_label_lst, ylim=[0, len(x_locs)])
plt.show()

但这只会导致程序崩溃并显示以下错误消息:“TypeError: barh() got multiple values for argument 'width'”宽度参数为 .15。

total_vals 包含 35 个计数,或我试图在 x 轴上绘制的频率。就像这些是我试图让我的酒吧反映在高度方面的价值观。 positive_vals 和neutral_vals 也包含35 个计数。

x_locs 是我根据在示例代码中看到的内容创建的变量,但这应该是数字 0-34。这只是应该指示我要显示的 35 个条形中的每一个。

让我感到困惑的是,当我删除 x_locs 时会发生什么。所以如果我只是这样做

 rects1 = ax.barh(total_vals, width=.15, color='r', label="total tweet count")

我得到了这个 matplotlib 图表,它似乎在图表的 x 轴上绘制了我的“宽度”参数/使宽度参数成为 x 轴的限制。

我的 yticks 看起来它们实际上至少按照它们应该运行的顺序正确显示,但似乎宽度是在 x 轴上绘制或测量的内容......显然,图表是空的.

我知道我的 yticklabels 现在非常长,我只是上传了这段代码,以便它可以重现。

我现在还不确定“y”参数实际上应该表示什么。文档说“每个条的 y 坐标”。我最初认为 y 参数应该只是我想要显示的计数,但后来我看到“left”参数是“条形左侧的 x 坐标”。

所以我将代码更改为

rects1 = ax.barh(y=x_locs, left=total_vals, width=.15, color='r', label="total tweet count")

这正确地改变了 y 轴,但它仍然给了我一个空图。我不知道我的计数/条发生了什么以及为什么它们根本没有显示。

我如何真正让条形图显示出来?我只是对这些水平条形图的参数实际工作方式有一些明显的困惑。

【问题讨论】:

  • 为了清楚起见,您希望图表中每个刻度的条形图是并排的,而不是堆叠的,对吧?
  • 是的,条形应该并排,而不是堆叠。一个给定的 ytick/label (如底部的“数字学习应用程序”)应该有 3 个条形图,每个条形图彼此下方。
  • 我正在寻找这个 stackoverflow 帖子中的条形图(虽然我认为我在原始问题中链接了这个......也许我没有)stackoverflow.com/questions/15201386/…

标签: python matplotlib


【解决方案1】:

您实际上非常接近您的代码;你只是对barh的参数有些困惑。

首先,让我们澄清所需的参数是。

第一个位置参数是y,它指的是每个类别的y坐标。因此,x_locs 是用词不当。这些可以很容易地按运行顺序创建:第一个类别在y=0,第二个类别在y=1,依此类推。

接下来,你传递了一个像total_vals 这样的变量,但也传递了width,然后得到一个错误。

考虑一个条形由两个方面定义,positionsize。由于所有条形都与绘图的左脊对齐,因此它们的 x 坐标是相同的,它们将仅由它们的 y 坐标定义,我们已经这样做了。

对于条形图,我们通常希望一个维度是动态的(代表某个数量的维度),而另一个维度对于所有条形图都是相同的。相同的是height,因为它等于条的垂直大小。

那么,另一个动态维度是width,它是代表total_valspositive_valsnegative_valswidth。因此,您收到了该错误,因为您试图指定每条柱的长度应为 两次

现在,让我们回到y_locs。请记住,我们希望每个刻度有 3 个柱,并排。这相当于说我们希望对 bar 的每个“类”(totalnegativepositive)进行微调,否则它们会重叠。

例如,我们可以让negative 的条保持在y_loc 指定的位置,positive 的条向下移动 10 个像素,total 的条向下移动 20 个像素。这是一个实施细节;重要的是我们认识到这种偏移的需要

将所有这些放在一起,我们得到:

import numpy as np
from matplotlib import pyplot as plt

fig, ax = plt.subplots(figsize=(6, 10))

t_label_lst = ['Digital Learning Apps', 'News, Events, Daily', 'News on School Events', 'STEM Extracurriculars & School Programs', 'Hiring, STEM Workforce', 'Women in STEM', 'Activities and Projects Outside of the Classroom', 'Ambiguous', 'Ambiguous, STEM in College', 'Next Generation of Engineers', 'News, Events, Daily', 'Educational Policy and Higher Education, Reform', 'STEM Activities, Building, Arts, and Design', 'Engaging students with STEM using programming and robotics', 'Black Leaders in STEM', 'Next Generation of Engineers', 'Ambiguous', 'Astronomy, NASA', 'STEM workshops and summer camps', 'Competitions, Team Credit', 'Ambiguous, Technology Hashtags', 'Google Education', 'Good Job Today! Crediting Daily Activities and Work', 'Engaging students with STEM using programming and robotics', 'Environmental Science', 'Teachers, Public Schools In STEM', 'Ambiguous', 'Edtech Companies', 'Ambiguous, PHD Conversation', 'Ambiguous', 'Engaging students with STEM using programming and robotics', 'Ambiguous, Virtual Reality and Personalized learning mention', 'Ambiguous', 'Ambiguous', 'Ambiguous, #Autism hashtag has disproportionate weight']

total_vals = [23668, 13186, 10752, 10002, 9558, 9126, 8138, 7389, 7006, 6965, 6859, 6621, 6538, 5700, 5110, 5069, 4419, 4025, 3943, 3866, 3761, 3697, 3543, 3294, 3067, 2928, 2511, 2491, 2353, 2312, 2229, 2175, 2021, 1921, 1787]
positive_vals = [9941, 9306, 7595, 5935, 5913, 7488, 5258, 4905, 4026, 5242, 5557, 3225, 3530, 3055, 3300, 3503, 2461, 2199, 2074, 2379, 1665, 2274, 2250, 1674, 1523, 1533, 1241, 859, 1504, 1419, 1132, 1082, 805, 753, 580]
neutral_vals = [13727, 3880, 3157, 4067, 3645, 1638, 2880, 2484, 2980, 1723, 1302, 3396, 3008, 2645, 1810, 1566, 1958, 1826, 1869, 1487, 2096, 1423, 1293, 1620, 1544, 1395, 1270, 1632, 849, 893, 1097, 1093, 1216, 1168, 1207]

bar_size = 0.25
padding = 0.25

y_locs = np.arange(len(total_vals)) * (bar_size * 3 + padding)

rects1 = ax.barh(y_locs, total_vals, align='edge', height=bar_size, color='r', label="total tweet count")
rects2 = ax.barh(y_locs + bar_size, positive_vals, align='edge', height=bar_size, color='b', label="positive tweet count")
rects3 = ax.barh(y_locs + 2 * bar_size, neutral_vals, align='edge', height=bar_size, color='yellow', label="neutral tweet count")
ax.set(yticks=x_locs, yticklabels=t_label_lst, ylim=[0 - padding, len(x_locs)])

【讨论】:

  • NameError: name 'x_locs' is not defined。应该是y_locs
【解决方案2】:

我认为简单的答案就是将 width 更改为 height,因为它是一个垂直图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-02
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多