title: Matplotlib: how to specify width of x-label bounding box
body: <p>I'm trying to create a stacked bar chart in MatPlotLib with two distinct x-labels on top and bottom. The upper one is supposed to have a bounding box with the same width as the bars themselves. </p>
  
  <p>Plot that's not quite right</p>
  
  <p><img src="https://i.stack.imgur.com/MTbZy.png" alt=""></p>
  
  <p>This is how I create the labels:</p>
  
  <pre><code>plt.tick_params(axis="both", left=False, bottom=False, labelleft=False)
  plt.xticks(ind, diagram.keys())
  ax.set_frame_on(False)
  
  for label, x in zip([q[1] for q in diagram.values()], ind):
      ax.text(
          x, 1.05, '{:4.0%}'.format(label), 
          ha="center", va="center", 
          bbox={"facecolor": "blue", "pad": 3}
      )
  </code></pre>
  
  <p><code>diagram</code> is a dictionary like <code>{bottom-label: [[contents], top-label]}</code></p>
  
  <p>So I guess my question boils down to: <strong>How do I manipulate the bounding boxs of the text objects?</strong> </p>
  
  <p>Thanks a lot!</p>
  
  <p>As per request, a runnable example:</p>
  
  <pre><code>import matplotlib.pyplot as plt
  import numpy as np
  
  
  def stacked_bar_chart(
          diagram, title="example question", img_name="test_image", width=0.7, clusters=None, show_axes=True,
          show_legend=True, show_score=True):
      """
      Builds one or multiple scaled stacked bar charts for grade
      distributions. saves image as png.
      :param show_score: whether the score should be shown on top
      :param show_legend: whether the legend should be shown
      :param show_axes: whether question name should be shown on bottom
      :param clusters: indices of clusters to be displayed.
      :param width: the width of the bars as fraction of available space
      :param title: diagram title
      :param img_name: output path
      :param diagram: dictionary: {x-label: [[grade distribution], score]}
      :return: nothing.
      """
  
      grades = {
          "sehr gut":     "#357100",
          "gut":          "#7fb96a",
          "befriedigend": "#fdd902",
          "ausreichend":  "#f18d04",
          "mangelhaft":   "#e3540e",
          "ungenügend":   "#882d23"
      }
  
      # select clusters
      if clusters is not None:
          diagram = {i: diagram[i] for i in clusters}
  
      # normalize score distribution =&gt; sum of votes = 1.0
      normalized = []
      for question in diagram.values():
          s = sum(question[0])
          normalized.append([x / s for x in question[0]])
  
      # transpose dict values (score distributions) to list of lists
      transformed = list(map(list, zip(*normalized)))
  
      # input values for diagram generation
      n = len(diagram)  # number of columns
      ind = np.arange(n)  # x values for bar center
      base = [0] * n  # lower bounds for individual color set
      bars = []
      fig, ax = plt.subplots()
  
      # loop over grades
      for name, grade in zip(grades.keys(), transformed):
          assert len(grade) == n, \
              "something went wrong in plotting grade stack " + img_name
          bar = plt.bar(ind, grade, width=width, color=grades[name], bottom=base)
          bars.append(bar)
  
          # loop over bars
          for i, (rect, score) in enumerate(zip(bar, grade)):
              # update lower bound for next bar section
              base[i] += grade[i]
              # label with percentage
              # TODO text color white
              ax.text(
                  rect.get_x() + width / 2, rect.get_height() / 2 + rect.get_y(), "{0:.0f}%".format(score * 100),
                  va="center", ha="center")
  
      # label diagram
  
      plt.suptitle(title)
      if show_axes:
          plt.tick_params(axis="both", left=False, bottom=False, labelleft=False)
          plt.xticks(ind, diagram.keys())
          ax.set_frame_on(False)
  
      else:
          plt.tick_params(axis="both", left=False, bottom=False, labelleft=False, labelbottom=False)
          plt.axis("off")
  
      # show score label above
      if show_score:
          for label, x in zip([q[1] for q in diagram.values()], ind):
              ax.text(
                  x, 1.05, '{:4.0%}'.format(label),
                  ha="center", va="center",
                  bbox={"facecolor": "blue", "pad": 3}
              )
  
      # create legend
      if show_legend:
          plt.legend(
              reversed(bars), reversed([*grades]),
              bbox_to_anchor=(1, 1), borderaxespad=0)
  
      # save file
      plt.show()
  
  
  diagram = {
      "q1": [[1, 2, 3, 4, 5, 6], 0.6],
      "q2": [[2, 3, 1, 2, 3, 1], 0.4]
  }
  stacked_bar_chart(diagram)
  </code></pre>