带有中心标签的堆积条形图

时间:2016-12-23 06:32:52

标签: python matplotlib

我正在努力"健壮地"将数据标签置于堆积条形图中心。下面给出一个简单的代码和结果。如您所见,数据标签并未真正集中在所有矩形中。我错过了什么?

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()

2 个答案:

答案 0 :(得分:6)

  • 以下方法更加简洁,并且更容易根据列数进行缩放。
  • 将数据放入pandas.DataFrame是绘制堆积条形图的最简单方法。
  • 使用pandas.DataFrame.plot.bar(stacked=True)是绘制堆积条形图的最简单方法。
    • 此方法返回其中的matplotlib.axes.Axesnumpy.ndarray
  • 使用.patches方法解压缩matplotlib.patches.Rectangle对象的列表,每个对象对应堆积条形的每个部分。
    • 每个.Rectangle都有提取定义矩形的各种值的方法。
    • 每个.Rectangle的顺序是从左到右,从下到上,因此在遍历.Rectangle时,每个级别的所有.patches对象都按顺序出现。 / li>
  • 标签是使用f-stringlabel_text = f'{height}'制作的,因此可以根据需要添加任何其他文本,例如label_text = f'{height}%'

进口

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})
df.index = ['C1', 'C2', 'C3']

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

情节

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()

enter image description here

  • 要绘制水平条:
  • kind='barh'
  • label_text = f'{width}'
  • 出处:jsoma/chart.py

答案 1 :(得分:4)

为什么你写了va="bottom"?您必须使用va="center"enter image description here