{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Building histograms using Rectangles and PolyCollections\n\nUsing a path patch to draw rectangles.\n\nThe technique of using lots of `.Rectangle` instances, or the faster method of\nusing `.PolyCollection`, were implemented before we had proper paths with\nmoveto, lineto, closepoly, etc. in Matplotlib. Now that we have them, we can\ndraw collections of regularly shaped objects with homogeneous properties more\nefficiently with a PathCollection. This example makes a histogram -- it's more\nwork to set up the vertex arrays at the outset, but it should be much faster\nfor large numbers of objects.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nimport matplotlib.patches as patches\nimport matplotlib.path as path\n\nnp.random.seed(19680801) # Fixing random state for reproducibility\n\n# histogram our data with numpy\ndata = np.random.randn(1000)\nn, bins = np.histogram(data, 50)\n\n# get the corners of the rectangles for the histogram\nleft = bins[:-1]\nright = bins[1:]\nbottom = np.zeros(len(left))\ntop = bottom + n\n\n# we need a (numrects x numsides x 2) numpy array for the path helper\n# function to build a compound path\nXY = np.array([[left, left, right, right], [bottom, top, top, bottom]]).T\n\n# get the Path object\nbarpath = path.Path.make_compound_path_from_polys(XY)\n\n# make a patch out of it, don't add a margin at y=0\npatch = patches.PathPatch(barpath)\npatch.sticky_edges.y[:] = [0]\n\nfig, ax = plt.subplots()\nax.add_patch(patch)\nax.autoscale_view()\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of creating a three-dimensional array and using\n`~.path.Path.make_compound_path_from_polys`, we could as well create the\ncompound path directly using vertices and codes as shown below\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "nrects = len(left)\nnverts = nrects*(1+3+1)\nverts = np.zeros((nverts, 2))\ncodes = np.ones(nverts, int) * path.Path.LINETO\ncodes[0::5] = path.Path.MOVETO\ncodes[4::5] = path.Path.CLOSEPOLY\nverts[0::5, 0] = left\nverts[0::5, 1] = bottom\nverts[1::5, 0] = left\nverts[1::5, 1] = top\nverts[2::5, 0] = right\nverts[2::5, 1] = top\nverts[3::5, 0] = right\nverts[3::5, 1] = bottom\n\nbarpath = path.Path(verts, codes)\n\n# make a patch out of it, don't add a margin at y=0\npatch = patches.PathPatch(barpath)\npatch.sticky_edges.y[:] = [0]\n\nfig, ax = plt.subplots()\nax.add_patch(patch)\nax.autoscale_view()\nplt.show()" ] }, { "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.patches`\n - `matplotlib.patches.PathPatch`\n - `matplotlib.path`\n - `matplotlib.path.Path`\n - `matplotlib.path.Path.make_compound_path_from_polys`\n - `matplotlib.axes.Axes.add_patch`\n - `matplotlib.collections.PathCollection`\n\n This example shows an alternative to\n\n - `matplotlib.collections.PolyCollection`\n - `matplotlib.axes.Axes.hist`\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.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }