{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# A pie and a donut with labels\n\nWelcome to the Matplotlib bakery. We will create a pie and a donut\nchart through the `pie method ` and\nshow how to label them with a `legend `\nas well as with the `pie_label method ` and\n`annotations `.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As usual we would start by defining the imports and create a figure with\nsubplots.\nNow it's time for the pie. Starting with a pie recipe, we create the data\nand a list of labels from it.\n\nWe then create the pie and store the returned `~matplotlib.container.PieContainer`\nobject for later.\n\nWe can provide the `~matplotlib.container.PieContainer` and a format string to\nthe `~matplotlib.axes.Axes.pie_label` method to automatically label each\ningredient's wedge with its weight in grams and percentages.\n\nThe `~.PieContainer` has a list of patches as one of its attributes. Those are\n`matplotlib.patches.Wedge` patches, which can directly be used as the handles\nfor a legend. We can use the legend's ``bbox_to_anchor`` argument to position\nthe legend outside of the pie. Here we use the axes coordinates ``(1, 0, 0.5,\n1)`` together with the location ``\"center left\"``; i.e. the left central\npoint of the legend will be at the left central point of the bounding box,\nspanning from ``(1, 0)`` to ``(1.5, 1)`` in axes coordinates.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nfig, ax = plt.subplots(figsize=(6, 3))\n\nrecipe = [\"375 g flour\",\n \"75 g sugar\",\n \"250 g butter\",\n \"300 g berries\"]\n\ndata = [int(x.split()[0]) for x in recipe]\ningredients = [x.split()[-1] for x in recipe]\n\npie = ax.pie(data)\n\nax.pie_label(pie, '{frac:.1%}\\n({absval:d}g)',\n textprops=dict(color=\"w\", size=8, weight=\"bold\"))\n\nax.legend(pie.wedges, ingredients,\n title=\"Ingredients\",\n loc=\"center left\",\n bbox_to_anchor=(1, 0, 0.5, 1))\n\nax.set_title(\"Matplotlib bakery: A pie\")\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now it's time for the donut. Starting with a donut recipe, we transcribe\nthe data to numbers (converting 1 egg to 50 g), and directly plot the pie.\nThe pie? Wait... it's going to be donut, is it not?\nWell, as we see here, the donut is a pie, having a certain ``width`` set to\nthe wedges, which is different from its radius. It's as easy as it gets.\nThis is done via the ``wedgeprops`` argument.\n\nWe then want to label the wedges via\n`annotations `. We first create some\ndictionaries of common properties, which we can later pass as keyword\nargument. We then iterate over all wedges and for each\n\n* calculate the angle of the wedge's center,\n* from that obtain the coordinates of the point at that angle on the\n circumference,\n* determine the horizontal alignment of the text, depending on which side\n of the circle the point lies,\n* update the connection style with the obtained angle to have the annotation\n arrow point outwards from the donut,\n* finally, create the annotation with all the previously\n determined parameters.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(6, 3), subplot_kw=dict(aspect=\"equal\"))\n\nrecipe = [\"225 g flour\",\n \"90 g sugar\",\n \"1 egg\",\n \"60 g butter\",\n \"100 ml milk\",\n \"1/2 package of yeast\"]\n\ndata = [225, 90, 50, 60, 100, 5]\n\npie = ax.pie(data, wedgeprops=dict(width=0.5), startangle=-40)\n\nbbox_props = dict(boxstyle=\"square,pad=0.3\", fc=\"w\", ec=\"k\", lw=0.72)\nkw = dict(arrowprops=dict(arrowstyle=\"-\"),\n bbox=bbox_props, zorder=0, va=\"center\")\n\nfor i, p in enumerate(pie.wedges):\n ang = (p.theta2 - p.theta1)/2. + p.theta1\n y = np.sin(np.deg2rad(ang))\n x = np.cos(np.deg2rad(ang))\n horizontalalignment = {-1: \"right\", 1: \"left\"}[int(np.sign(x))]\n connectionstyle = f\"angle,angleA=0,angleB={ang}\"\n kw[\"arrowprops\"].update({\"connectionstyle\": connectionstyle})\n ax.annotate(recipe[i], xy=(x, y), xytext=(1.35*np.sign(x), 1.4*y),\n horizontalalignment=horizontalalignment, **kw)\n\nax.set_title(\"Matplotlib bakery: A donut\")\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And here it is, the donut. Note however, that if we were to use this recipe,\nthe ingredients would suffice for around 6 donuts - producing one huge\ndonut is untested and might result in kitchen errors.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. admonition:: References\n\n The use of the following functions, methods, classes and modules is shown\n in this example:\n\n - `matplotlib.axes.Axes.pie` / `matplotlib.pyplot.pie`\n - `matplotlib.axes.Axes.pie_label` / `matplotlib.pyplot.pie_label`\n - `matplotlib.axes.Axes.legend` / `matplotlib.pyplot.legend`\n\n.. tags::\n\n component: label\n component: annotation\n plot-type: pie\n level: beginner\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.15" } }, "nbformat": 4, "nbformat_minor": 0 }