带有居中标签的堆叠条形图

2024-02-13

我试图“稳健地”将数据标签集中在堆积条形图中。下面给出了一个简单的代码示例和结果。正如您所看到的,数据标签并未真正在所有矩形中居中。我缺少什么?

import numpy as np
import matplotlib.pyplot as plt

A = [45, 17, 47]
B = [91, 70, 72]

fig = plt.figure(facecolor="white")

ax = fig.add_subplot(1, 1, 1)
bar_width = 0.5
bar_l = np.arange(1, 4)
tick_pos = [i + (bar_width / 2) for i in bar_l]

ax1 = ax.bar(bar_l, A, width=bar_width, label="A", color="green")
ax2 = ax.bar(bar_l, B, bottom=A, width=bar_width, label="B", color="blue")
ax.set_ylabel("Count", fontsize=18)
ax.set_xlabel("Class", fontsize=18)
ax.legend(loc="best")
plt.xticks(tick_pos, ["C1", "C2", "C3"], fontsize=16)
plt.yticks(fontsize=16)

for r1, r2 in zip(ax1, ax2):
    h1 = r1.get_height()
    h2 = r2.get_height()
    plt.text(r1.get_x() + r1.get_width() / 2., h1 / 2., "%d" % h1, ha="center", va="bottom", color="white", fontsize=16, fontweight="bold")
    plt.text(r2.get_x() + r2.get_width() / 2., h1 + h2 / 2., "%d" % h2, ha="center", va="bottom", color="white", fontsize=16, fontweight="bold")

plt.show()

  • 以下方法更简洁,并且易于扩展。
  • 将数据放入pandas.DataFrame是绘制堆积条形图的最简单方法。
  • Using pandas.DataFrame.plot.bar(stacked=True) https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.bar.html, or pandas.DataFrame.plot(kind='bar', stacked=True) https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html, is the easiest way to plot a stacked bar plot.
    • 该方法返回一个matplotlib.axes.Axes or a numpy.ndarray其中。
  • Since seaborn只是一个高级 APImatplotlib,这些解决方案也适用于seaborn绘图,如图所示如何使用聚合值注释seaborn条形图 https://stackoverflow.com/a/64797097/7758804.
  • 对于水平堆叠条,请参见水平堆叠条形图并向每个部分添加标签 https://stackoverflow.com/a/64202669/7758804
  • 测试于python 3.10, pandas 1.4.2, matplotlib 3.5.1, seaborn 0.11.2

导入和测试 DataFrame

import pandas as pd
import matplotlib.pyplot as plt

A = [45, 17, 47]
B = [91, 70, 72]
C = [68, 43, 13]

# pandas dataframe
df = pd.DataFrame(data={'A': A, 'B': B, 'C': C}, index=['C1', 'C2', 'C3'])

     A   B   C
C1  45  91  68
C2  17  70  43
C3  47  72  13

更新为matplotlib v3.4.2

  • Use matplotlib.pyplot.bar_label https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar_label.html,这将自动将条中的值居中。
  • See 如何在条形图上添加值标签 https://stackoverflow.com/a/67561982/7758804有关更多详细信息和示例,请使用.bar_label.
  • 测试用pandas v1.2.4,正在使用matplotlib作为情节引擎。
  • 如果条形图的某些部分为零,请参阅我的answer https://stackoverflow.com/a/64202669/7758804,它展示了如何自定义labels for .bar_label().
  • ax.bar_label(c, fmt='%0.0f', label_type='center')如果需要,将更改数字格式以不显示小数位。
ax = df.plot(kind='bar', stacked=True, figsize=(8, 6), rot=0, xlabel='Class', ylabel='Count')
for c in ax.containers:

    # Optional: if the segment is small or 0, customize the labels
    labels = [v.get_height() if v.get_height() > 0 else '' for v in c]
    
    # remove the labels parameter if it's not needed for customized labels
    ax.bar_label(c, labels=labels, label_type='center')

可以使用用于删除小段标签的其他选项fmt

  • 随着matplotlib 3.7 更新 https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.7.0.html#additional-format-string-options-in-bar-label, the fmt的论证bar_label现在接受 {} 样式格式字符串。
  • fmt=lambda x: f'{x:.0f}' if x > 0 else ''
  • fmt=lambda x: np.where(x > 0, f'{x:.0f}', '') with np.where https://numpy.org/doc/stable/reference/generated/numpy.where.html
ax = df.plot(kind='bar', stacked=True, figsize=(8, 6), rot=0, xlabel='Class', ylabel='Count')
for c in ax.containers:
    ax.bar_label(c, fmt=lambda x: f'{x:.0f}' if x > 0 else '', label_type='center')

希博恩选项

  • seaborn是一个高级 APImatplotlib
  • The seaborn.barplot https://seaborn.pydata.org/generated/seaborn.barplot.htmlapi 没有堆叠选项,但它“可以”通过以下方式实现sns.histplot https://seaborn.pydata.org/generated/seaborn.histplot.html, or sns.displot https://seaborn.pydata.org/generated/seaborn.displot.html.

Seaborn 数据帧格式

# create the data frame
df = pd.DataFrame(data={'A': A, 'B': B, 'C': C, 'cat': ['C1', 'C2', 'C3']})

    A   B   C cat
0  45  91  68  C1
1  17  70  43  C2
2  47  72  13  C3

# convert the dataframe to a long form
df = df.melt(id_vars='cat')

  cat variable  value
0  C1        A     45
1  C2        A     17
2  C3        A     47
3  C1        B     91
4  C2        B     70
5  C3        B     72
6  C1        C     68
7  C2        C     43
8  C3        C     13

轴级图

# plot
ax = sns.histplot(data=df, x='cat', hue='variable', weights='value', discrete=True, multiple='stack')

# iterate through each container
for c in ax.containers:

    # Optional: if the segment is small or 0, customize the labels
    labels = [v.get_height() if v.get_height() > 0 else '' for v in c]
    
    # remove the labels parameter if it's not needed for customized labels
    ax.bar_label(c, labels=labels, label_type='center')

图形级图

# plot
g = sns.displot(data=df, x='cat', hue='variable', weights='value', discrete=True, multiple='stack')

# iterate through each axes
for ax in g.axes.flat:

    # iterate through each container
    for c in ax.containers:

        # Optional: if the segment is small or 0, customize the labels
        labels = [v.get_height() if v.get_height() > 0 else '' for v in c]

        # remove the labels parameter if it's not needed for customized labels
        ax.bar_label(c, labels=labels, label_type='center')

原答案

  • Using the .patches method unpacks a list of matplotlib.patches.Rectangle https://matplotlib.org/api/_as_gen/matplotlib.patches.Rectangle.html?highlight=rectangle#matplotlib.patches.Rectangle objects, one for each of the sections of the stacked bar.
    • Each .Rectangle具有提取定义矩形的各种值的方法。
    • Each .Rectangle是从左到右、从下到上的顺序,所以所有的.Rectangle迭代时,每个级别的对象按顺序出现.patches.
  • The labels are made using an f-string https://www.python.org/dev/peps/pep-0498/, label_text = f'{height}', so any additional text can be added as needed, such as label_text = f'{height}%'
    • label_text = f'{height:0.0f}'将显示没有小数位的数字。

Plot

plt.style.use('ggplot')

ax = df.plot(stacked=True, kind='bar', figsize=(12, 8), rot='horizontal')

# .patches is everything inside of the chart
for rect in ax.patches:
    # Find where everything is located
    height = rect.get_height()
    width = rect.get_width()
    x = rect.get_x()
    y = rect.get_y()
    
    # The height of the bar is the data value and can be used as the label
    label_text = f'{height}'  # f'{height:.2f}' to format decimal values
    
    # ax.text(x, y, text)
    label_x = x + width / 2
    label_y = y + height / 2

    # plot only when height is greater than specified value
    if height > 0:
        ax.text(label_x, label_y, label_text, ha='center', va='center', fontsize=8)
    
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)    
ax.set_ylabel("Count", fontsize=18)
ax.set_xlabel("Class", fontsize=18)
plt.show()
  • To plot a horizontal bar:
    • kind='barh'
    • label_text = f'{width}'
    • if width > 0:
  • 归因:jsoma/chart.py https://gist.github.com/jsoma/c61e56819e4ae315ad5d194a630ccb23
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有居中标签的堆叠条形图 的相关文章

随机推荐

  • 如何在octobercms中过滤多个类别的博客文章?

    October CMS如何过滤多个类别的博文 我正在使用 RainLab 博客插件 该插件仅允许过滤一种类别 我想要一个综合结果 请帮忙 您将需要使用一些自定义代码来根据多个类别进行过滤 如果仍然使用 PostList 组件 请进行以下更改
  • iOS 编程中的中心地图

    我们如何在地图中关注用户 我想让蓝点 用户位置 位于地图的中心 但我还允许用户放大和缩小 然后在几秒钟后放大回用户位置 我对解决方案的有根据的猜测 我们检测用户是否正在放大或缩小 在没有放大或缩小检测的三秒后 我们开始跟随用户 你的帮助会很
  • IEnumerable 的性能比较和源中每个项目的引发事件?

    我想读取包含数百万条记录的大型二进制文件 并且我想获取一些记录报告 我用BinaryReader读取 我认为在读取器中具有最佳性能 并将读取的字节转换为数据模型 由于记录的数量 将模型传递到报表层是另一个问题 我更喜欢使用IEnumerab
  • 在 WSO2 ESB 中介期间修改配置注册表资源内容

    我有一个场景 我需要在配置注册表中存储简单计数器并在序列流结束时递增它 我们需要存储在配置注册表中的原因是 如果服务器重新启动 我们将保留最后的计数器值 有人可以建议如何增加配置注册表中的计数器吗 您可以在中介中使用示例 javascrip
  • “等待返回”有什么区别吗? [复制]

    这个问题在这里已经有答案了 有什么区别吗 const foo async gt some other code that uses await return await bar and const foo async gt some oth
  • Gradle - 仅执行单一构建类型

    我在 build gradle 中定义了多种构建类型 在变体窗口中 我选择了构建变体 例如 debugAPI23 我预计只会执行一种构建类型中的代码 但在 Gradle Console 中我可以看到所有构建类型的输出 正如您所看到的 我正在
  • 在同一地址多次放置 new 是否定义明确/合法?

    注意 这个问题的动机是试图提出预处理器黑客技术来生成无操作分配来回答另一个问题 接受新对象的宏 https stackoverflow com questions 7522949 c macro that accent new object
  • 路由的处理程序无效 - Wordpress

    我正在尝试使用类在 WordPress 中创建自定义 REST API 端点 我也用传统的方式做了同样的事情 效果很好 但是 使用类时我收到错误The handler for the route is invalid 代码 class CS
  • 谁能解释一下android中未绑定服务和绑定服务之间的区别

    任何人都可以解释一下android中未绑定服务和绑定服务之间的区别 并解释一下意图服务 Thanks 绑定服务 http developer android com guide components bound services html
  • 制作堆叠矩形而不是列的直方图

    使用以下代码 我得到如下的直方图 x lt rnorm 100 hist x col gray 我该怎么做才能将条形显示为堆叠矩形 通过其轮廓可见 而不是填充颜色的变化 而不是统一的列 每个矩形代表一个频率 例如 1 尽管我希望能够通过参数
  • 使用 dropzone.js 发送附加参数

    我正在尝试添加 dropzone js 并且想通过 file 传递另一个参数 因此我将隐藏输入放入 form 中 我可以上传文件并可以在Java部分读取它 但我无法读取type chooser WebKitFormBoundaryZxF6M
  • 我的上网IP是多少

    我的电脑上安装了两张网卡 一个用于互联网连接 另一个用于与客户端计算机共享互联网 我用这段代码获取我的IP IPHostEntry HosyEntry Dns GetHostEntry Dns GetHostName foreach IPA
  • Mustache Templates可以做模板扩展吗?

    我是小胡子的新手 许多模板语言 例如 Django Jinja 会让你像这样扩展 父 模板 基本 html block content endblock 首页 html extends base html block content h1
  • 如何从 mysql 数据库中删除重复的条目?

    我有一个包含一些 id 标题的表 我想让标题列唯一 但它已经有超过 600k 条记录 其中一些是重复的 有时是几十次 如何删除除一个之外的所有重复项 以便我可以在之后的标题列中添加一个 UNIQUE 键 此命令添加唯一键 并删除生成错误 由
  • Quarkus - SmallRye 反应式消息传递 - RabbitMQ:将消息发送到默认交换

    使用远程过程调用 https www rabbitmq com tutorials tutorial six java html模式 我需要将答案发送到回复队列 即我需要将消息发送到默认交换机 并以队列名称作为路由键 我在 Quarkus
  • JACOB 和 jre 1.7 出现 UnsatisfiedLinkError

    我编写了一个使用 JACOB 访问 iTunes 的程序 它在 Eclipse 中工作正常 但是当我导出它并在命令提示符中运行它时 我收到一个不满意的链接错误 告诉我 jacob 1 17 M2 x86 dll 是不在我的 java lib
  • 如何在 Android Wear 设备上运行 Xamarin.Forms 应用程序

    我怎样才能运行Xamarin Forms Platform Android FormsApplicationActivity在 Android Wear 设备上 电话base OnCreate bundle 在 的里面onCreate我的类
  • Xcode Instruments:泄漏 - 应用程序在启动时崩溃

    Xcode Instruments 泄漏 应用程序在启动时崩溃 该应用程序在设备和模拟器中都会崩溃 什么可能导致应用程序在连接仪器时崩溃 而在使用电缆或通过 Fabric 无线安装时正常工作 Update Launching the All
  • 如何在 Servicestack 中隐藏 Swagger UI 的端点?

    我正在使用 ServiceStack 3 9 59 0 的 Swagger 插件 我的 ServiceStack API 中有一些端点 例如 selfchecknode 我不想在 Swagger UI 中显示它们 是否有一种声明性方式 也许
  • 带有居中标签的堆叠条形图

    我试图 稳健地 将数据标签集中在堆积条形图中 下面给出了一个简单的代码示例和结果 正如您所看到的 数据标签并未真正在所有矩形中居中 我缺少什么 import numpy as np import matplotlib pyplot as p