diff --git a/AnatomyOfMatplotlib-Part2-Plotting_Methods_Overview.ipynb b/AnatomyOfMatplotlib-Part2-Plotting_Methods_Overview.ipynb new file mode 100644 index 0000000..cb44d34 --- /dev/null +++ b/AnatomyOfMatplotlib-Part2-Plotting_Methods_Overview.ipynb @@ -0,0 +1,406 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + }, + "name": "" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 2: Visual Overview of Plotting Functions\n", + "\n", + "We've talked a lot about laying things out, etc, but we haven't talked about actually plotting data yet. Matplotlib has a number of different plotting functions -- many more than we'll cover here, in fact. There's a more complete list in the pyplot documentation, and matplotlib gallery is a great place to get examples of all of them. \n", + "\n", + "However, a full list and/or the gallery can be a bit overwhelming at first. Instead we'll condense it down a bit, give you a look at some of the ones you're most likely to use, and then go over a subset of those in more detail.\n", + "\n", + "Here's a simplified visual overview of matplotlib's most commonly used plot types. Let's browse through these, and then we'll go over a few in more detail. Clicking on any of these images will take you to the code that generated them. We'll skip that for now, but feel browse through it later." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Basics: 1D series/points\n", + "### What we've mentioned so far\n", + "\n", + "\n", + "### Other common plot types\n", + "\n", + "\n", + "\n", + "## 2D Arrays and Images\n", + "\n", + "\n", + "\n", + "\n", + "## Vector Fields\n", + "\n", + "\n", + "## Data Distributions\n", + "" + ] + }, + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "Detailed Examples (of a few of these)" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# Let's get our standard imports out of the way\n", + "from __future__ import print_function\n", + "import numpy as np\n", + "import matplotlib\n", + "matplotlib.use('nbagg')\n", + "import matplotlib.pyplot as plt" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Input Data: 1D Series\n", + "\n", + "We've briefly mentioned `ax.plot(x, y)` and `ax.scatter(x, y)` to draw lines and points, respectively. We'll cover some of their options (markers, colors, linestyles, etc) in the next section.\n", + "\n", + "Rather than revisiting `plot` and `scatter`, let's move on to a couple of other common plot styles.\n", + "\n", + "### Bar Plots: `ax.bar(...)` and `ax.barh(...)`\n", + "\n", + "\n", + "Bar plots are one of the most common plot types. Matplotlib's `ax.bar(...)` method can also plot general rectangles, but the default is optimized for a simple sequence of x, y values, where the rectangles have a constant width. There's also `ax.barh(...)`, which makes a constant-height assumption instead of a constant-width assumption." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "np.random.seed(1)\n", + "x = np.arange(5)\n", + "y = np.random.randn(5)\n", + "\n", + "fig, axes = plt.subplots(ncols=2, figsize=plt.figaspect(0.4))\n", + "\n", + "vert_bars = axes[0].bar(x, y, color='lightblue', align='center')\n", + "horiz_bars = axes[1].barh(x, y, color='lightblue', align='center')\n", + "\n", + "# I'll also introduce axhline & axvline to draw a line all the way across the axes\n", + "axes[0].axhline(0, color='gray', linewidth=2)\n", + "axes[1].axvline(0, color='gray', linewidth=2)\n", + "\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that we held on to what `ax.bar(...)` returned. Matplotlib plotting methods return an `Artist` or a sequence of artists. Anything you can see in a matplotlib figure/axes/etc is an `Artist` of some sort.\n", + "\n", + "Let's re-visit that last example and modify what's plotted. In the case of `bar`, a container artist is returned, so we'll modify its contents instead of the container itself (thus `for bar in vert_bars`)." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "fig, ax = plt.subplots()\n", + "vert_bars = ax.bar(x, y, color='lightblue', align='center')\n", + "\n", + "# We could do this with two separate calls to `ax.bar` and numpy boolean indexing, as well.\n", + "for bar in vert_bars:\n", + " if bar.xy[1] < 0:\n", + " bar.set(edgecolor='darkred', color='salmon', linewidth=3)\n", + "\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Keep in mind that any plotting method in matplotlib returns the artists that are plotted. We'll use it again, particularly when we get to adding colorbars to images." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Filled Regions: `ax.fill(x, y)`, `fill_between(...)`, etc\n", + "\n", + "\n", + "Of these functions, `ax.fill_between(...)` is probably the one you'll use the most often. In its most basic form, it fills between the given y-values and 0:" + ] + }, + { + "cell_type": "code", + "collapsed": true, + "input": [ + "np.random.seed(1)\n", + "y = np.random.randn(100).cumsum()\n", + "x = np.linspace(0, 10, 100)\n", + "\n", + "fig, ax = plt.subplots()\n", + "ax.fill_between(x, y, color='lightblue')\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "However, it can also be used to fill between two curves. This is particularly useful when you want to show an envelope of some sort (e.g. error, confidence, amplitude, etc)." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "x = np.linspace(0, 10, 200)\n", + "y1 = 2 * x + 1\n", + "y2 = 3 * x + 1.2\n", + "y_mean = 0.5 * x * np.cos(2*x) + 2.5 * x + 1.1\n", + "\n", + "fig, ax = plt.subplots()\n", + "\n", + "# Plot the envelope with `fill_between`\n", + "ax.fill_between(x, y1, y2, color='yellow')\n", + "\n", + "# Plot the \"centerline\" with `plot`\n", + "ax.plot(x, y_mean, color='black')\n", + "\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Exercise 2.1:\n", + "\n", + "Now let's try combining `bar` and `fill_between` to make a nice prediction of what will happen as this class progresses:\n", + "\n", + "Can you reproduce the figure below?\n", + "" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%load exercises/2.1-bar_and_fill_between.py" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Input Data: 2D Arrays or Images\n", + "\n", + "There are several options for plotting 2D datasets. `imshow`, `pcolor`, and `pcolormesh` have a lot of overlap, at first glance. (The example image below is meant to clarify that somewhat.)\n", + "\n", + "\n", + "\n", + "\n", + "In short, `imshow` can interpolate and display large arrays very quickly, while `pcolormesh` and `pcolor` are much slower, but can handle much flexible (i.e. more than just rectangular) arrangements of cells.\n", + "\n", + "We won't dwell too much on the differences and overlaps here. They have overlapping capabilities, but different default behavior because their primary use-cases are a bit different (there's also `matshow`, which is `imshow` with different defaults). \n", + "\n", + "Instead we'll focus on what they have in common.\n", + "\n", + "`imshow`, `pcolor`, `pcolormesh`, `scatter`, and any other matplotlib plotting methods that map a range of data values onto a colormap return artists that are instances of `ScalarMappable.` In practice, what that means is a) you can display a colorbar for them, and b) they share several keyword arguments." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Colorbars\n", + "\n", + "Next, let's add a colorbar to the figure to display what colors correspond to values of `data` we've plotted. " + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from matplotlib.cbook import get_sample_data\n", + "data = np.load(get_sample_data('axes_grid/bivariate_normal.npy'))\n", + "\n", + "fig, ax = plt.subplots()\n", + "im = ax.imshow(data, cmap='gist_earth')\n", + "fig.colorbar(im)\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may notice that `colorbar` is a `Figure` method and not an `Axes` method. That's because `colorbar` doesn't operate on the axes. Instead, it shrinks the current axes by a bit, adds a _new_ axes to the figure, and places the colorbar on that axes.\n", + "\n", + "The new axes that `fig.colorbar` creates is fairly limited in where it can be positioned. For example, it's always outside the axes it \"steals\" room from. Sometimes you may want to avoid \"stealing\" room from an axes or maybe even have the colorbar _inside_ another axes. In that case, you can manually create the axes for the colorbar and position it where you'd like:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "fig, ax = plt.subplots()\n", + "cax = fig.add_axes([0.27, 0.8, 0.5, 0.05])\n", + "\n", + "im = ax.imshow(data, cmap='gist_earth')\n", + "fig.colorbar(im, cax=cax, orientation='horizontal')\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One note: In the last module in this tutorial, we'll briefly cover `axes_grid`, which is very useful for aligning colorbars and/or other axes with images displayed with `imshow`. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " ### Shared parameters for `imshow`, `pcolormesh`, `contour`, `scatter`, etc\n", + " \n", + " As we mentioned earlier, any plotting method that creates a `ScalarMappable` will have some common kwargs. The ones you'll use the most frequently are:\n", + " \n", + " * `cmap` : The colormap (or name of the colormap) used to display the input. (We'll go over the different colormaps in the next section.)\n", + " * `vmin` : The minimum data value that will correspond to the \"bottom\" of the colormap (defaults to the minimum of your input data).\n", + " * `vmax` : The maximum data value that will correspond to the \"top\" of the colormap (defaults to the maximum of your input data).\n", + " * `norm` : A `Normalize` instance to control how the data values are mapped to the colormap. By default, this will be a linear scaling between `vmin` and `vmax`, but other norms are available (e.g. `LogNorm`, `PowerNorm`, etc).\n", + " \n", + "`vmin` and `vmax` are particularly useful. Quite often, you'll want the colors to be mapped to a set range of data values, which aren't the min/max of your input data. For example, you might want a symmetric ranges of values around 0.\n", + "\n", + "As an example of that, let's use a divergent colormap with the data we showed earlier. We'll also use `interpolation=\"nearest\"` to \"turn off\" interpolation of the cells in the input dataset:" + ] + }, + { + "cell_type": "code", + "collapsed": true, + "input": [ + "from matplotlib.cbook import get_sample_data\n", + "data = np.load(get_sample_data('axes_grid/bivariate_normal.npy'))\n", + "\n", + "fig, ax = plt.subplots()\n", + "im = ax.imshow(data, cmap='seismic', interpolation='nearest')\n", + "fig.colorbar(im)\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, we'd really like the white in the colormap to correspond to 0. A quick way to do this is to make the `vmin` equal to the negative of the `vmax`. " + ] + }, + { + "cell_type": "code", + "collapsed": true, + "input": [ + "fig, ax = plt.subplots()\n", + "im = ax.imshow(data, cmap='seismic', interpolation='nearest',\n", + " vmin=-2, vmax=2)\n", + "fig.colorbar(im)\n", + "plt.show()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`vmin` and `vmax` are also very useful when we want multiple plots to share one colorbar, as our next exercise will do.\n", + "\n", + "## Exercise 2.2:\n", + "\n", + "Can you reproduce the figure below?\n", + "" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%load exercises/2.2-vmin_vmax_imshow_and_colorbars.py" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": null + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/AnatomyOfMatplotlib-Part3-HowToSpeakMPL.ipynb b/AnatomyOfMatplotlib-Part3-HowToSpeakMPL.ipynb index a9ab5be..e756d09 100644 --- a/AnatomyOfMatplotlib-Part3-HowToSpeakMPL.ipynb +++ b/AnatomyOfMatplotlib-Part3-HowToSpeakMPL.ipynb @@ -46,11 +46,11 @@ "metadata": {}, "source": [ "# How to speak \"MPL\"\n", - "In the previous part, you learned how matplotlib organizes plot-making by figures and axes. We broke down the components of a basic figure and learned how to create them. You also learned how to add one or more axes to a figure, and how to tie them together. You even learned how to change some of the basic appearances of the axes. Finally, we went over some of the many kinds of figures that matplotlib can generate. With all that knowledge, you should be off making great and wonderful figures. Why are you still here?\n", + "In the previous parts, you learned how matplotlib organizes plot-making by figures and axes. We broke down the components of a basic figure and learned how to create them. You also learned how to add one or more axes to a figure, and how to tie them together. You even learned how to change some of the basic appearances of the axes. Finally, we went over some of the many plotting methods that matplotlib has to draw on those axes. With all that knowledge, you should be off making great and wonderful figures. Why are you still here?\n", "\n", "\"We don't know how to control our plots and figures!\" says some random voice in the back of the room.\n", "\n", - "Of course! While the previous section may have taught you some of the structure and syntax of matplotlib, it did not describe much of the substance and vocabulary of the library. This section will go over many of the properties that are used throughout the library. Note that while many of the examples in this section may show one way of setting a particular property, that property may be applicible elsewhere in completely different context. This is the \"language\" of matplotlib.\n", + "Of course! While the previous sections may have taught you some of the structure and syntax of matplotlib, it did not describe much of the substance and vocabulary of the library. This section will go over many of the properties that are used throughout the library. Note that while many of the examples in this section may show one way of setting a particular property, that property may be applicible elsewhere in completely different context. This is the \"language\" of matplotlib.\n", "\n", "# Colors\n", "This is, perhaps, the most important piece of vocabulary in matplotlib. Given that matplotlib is a plotting library, colors are associated with everything that is plotted in your figures. Matplotlib supports a [very robust language](http://matplotlib.org/api/colors_api.html#module-matplotlib.colors) for specifying colors that should be familiar to a wide variety of users.\n", diff --git a/AnatomyOfMatplotlib-Part2-Limits_Legends_and_Layouts.ipynb b/AnatomyOfMatplotlib-Part4-Limits_Legends_and_Layouts.ipynb similarity index 94% rename from AnatomyOfMatplotlib-Part2-Limits_Legends_and_Layouts.ipynb rename to AnatomyOfMatplotlib-Part4-Limits_Legends_and_Layouts.ipynb index affc830..26dbf76 100644 --- a/AnatomyOfMatplotlib-Part2-Limits_Legends_and_Layouts.ipynb +++ b/AnatomyOfMatplotlib-Part4-Limits_Legends_and_Layouts.ipynb @@ -38,7 +38,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -71,7 +72,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -100,7 +102,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -147,7 +150,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -172,7 +176,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "code", @@ -188,7 +193,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -214,7 +220,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -224,9 +231,7 @@ "\n", " ax.legend(loc=\"best\")\n", " \n", - "Also, if you happen to be plotting something that you do not want to appear in the legend, just set the label to \"\\_nolegend\\_\". \n", - "\n", - "On a side note, we're going to briefly introduce the `ax.bar` plotting method here. Unsurprisingly, it draws bars (vertical, by default)." + "Also, if you happen to be plotting something that you do not want to appear in the legend, just set the label to \"\\_nolegend\\_\". " ] }, { @@ -241,17 +246,18 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# Exercise 2.1\n", + "# Exercise 4.1\n", "\n", "Once again, let's use a bit of what we've learned. Try to reproduce the following figure:\n", "\n", - "\n", + "\n", "\n", "Hint: You'll need to combine `ax.axis(...)` and `ax.margins(...)`. Here's the data and some code to get you started:" ] @@ -274,7 +280,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -312,7 +319,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -340,7 +348,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -362,7 +371,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -398,7 +408,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -427,7 +438,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -452,7 +464,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -492,7 +505,8 @@ ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": null }, { "cell_type": "markdown", @@ -502,7 +516,7 @@ "\n", "This one is a bit trickier. Once again, try to reproduce the figure below:\n", "\n", - "\n", + "\n", "\n", "\n", "A few key hints: The two subplots have no vertical space between them (this means that the `hspace` is `0`). Note that the bottom spine is at 0 in data coordinates and the tick lines are missing from the left and top sides.\n", @@ -515,23 +529,15 @@ "cell_type": "code", "collapsed": false, "input": [ - "# %load exercises/2.2-spines_ticks_and_subplot_spacing.py\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "\n", - "# Try to reproduce the figure shown in images/exercise_2.2.png\n", - "# This one is a bit trickier!\n", - "\n", - "# Here's the data...\n", - "data = [('dogs', 4, 4), ('frogs', -3, 1), ('cats', 1, 5), ('goldfish', -2, 2)]\n", - "animals, friendliness, popularity = zip(*data)\n" + "%load exercises/4.2-spines_ticks_and_subplot_spacing.py" ], "language": "python", "metadata": {}, - "outputs": [] + "outputs": [], + "prompt_number": 5 } ], "metadata": {} } ] -} +} \ No newline at end of file diff --git a/AnatomyOfMatplotlib-Part4-Artists.ipynb b/AnatomyOfMatplotlib-Part5-Artists.ipynb similarity index 99% rename from AnatomyOfMatplotlib-Part4-Artists.ipynb rename to AnatomyOfMatplotlib-Part5-Artists.ipynb index 4d61195..307dd1f 100644 --- a/AnatomyOfMatplotlib-Part4-Artists.ipynb +++ b/AnatomyOfMatplotlib-Part5-Artists.ipynb @@ -283,7 +283,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Exercise 4.1\n", + "## Exercise 5.1\n", "Give yourselves 4 gold stars!\n", "\n", "Hint: [StarPolygonCollection](http://matplotlib.org/api/collections_api.html#matplotlib.collections.StarPolygonCollection)" @@ -293,7 +293,7 @@ "cell_type": "code", "collapsed": false, "input": [ - "%load exercises/4.1-goldstar.py" + "%load exercises/5.1-goldstar.py" ], "language": "python", "metadata": {}, diff --git a/AnatomyOfMatplotlib-Part5-mpl_toolkits.ipynb b/AnatomyOfMatplotlib-Part6-mpl_toolkits.ipynb similarity index 100% rename from AnatomyOfMatplotlib-Part5-mpl_toolkits.ipynb rename to AnatomyOfMatplotlib-Part6-mpl_toolkits.ipynb diff --git a/README.md b/README.md index 7e4c822..b83314b 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,19 @@ for conferences and other opportunities for training. The tutorial can be viewed on [nbviewer](http://nbviewer.ipython.org): * [Part 0: Introduction To NumPy] * [Part 1: Overview of Matplotlib] -* [Part 2: Limits, Legends, and Layouts] +* [Part 2: Plotting Methods] * [Part 3: How To Speak MPL] -* [Part 4: Artists] -* [Part 5: mpl_toolkits] +* [Part 4: Limits, Legends, and Layouts] +* [Part 5: Artists] +* [Part 6: mpl_toolkits] Cheers! [Part 0: Introduction To NumPy]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part0-Intro2NumPy.ipynb [Part 1: Overview of Matplotlib]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part1-Figures_Subplots_and_layouts.ipynb -[Part 2: Limits, Legends, and Layouts]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part2-Limits_Legends_and_Layouts.ipynb +[Part 2: Plotting Methods]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part2-Plotting_Methods_Overview.ipynb [Part 3: How To Speak MPL]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part3-HowToSpeakMPL.ipynb -[Part 4: Artists]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part4-Artists.ipynb -[Part 5: mpl_toolkits]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part5-mpl_toolkits.ipynb +[Part 4: Limits, Legends, and Layouts]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part4-Limits_Legends_and_Layouts.ipynb +[Part 5: Artists]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part5-Artists.ipynb +[Part 6: mpl_toolkits]: http://nbviewer.ipython.org/github/WeatherGod/AnatomyOfMatplotlib/blob/master/AnatomyOfMatplotlib-Part6-mpl_toolkits.ipynb diff --git a/examples/.example_utils.py.swo b/examples/.example_utils.py.swo new file mode 100644 index 0000000..60e318f Binary files /dev/null and b/examples/.example_utils.py.swo differ diff --git a/examples/bar_example.py b/examples/bar_example.py new file mode 100644 index 0000000..24688f7 --- /dev/null +++ b/examples/bar_example.py @@ -0,0 +1,45 @@ +import numpy as np +import matplotlib.pyplot as plt + +import example_utils + +def main(): + fig, axes = example_utils.setup_axes() + + basic_bar(axes[0]) + tornado(axes[1]) + general(axes[2]) + + example_utils.title(fig, '"ax.bar(...)": Plot rectangles') + fig.savefig('bar_example.png', facecolor='none') + plt.show() + +def basic_bar(ax): + y = [1, 3, 4, 5.5, 3, 2] + err = [0.2, 1, 2.5, 1, 1, 0.5] + x = np.arange(len(y)) + ax.bar(x, y, yerr=err, color='lightblue', ecolor='black') + ax.margins(0.05) + ax.set_ylim(bottom=0) + example_utils.label(ax, 'bar(x, y, yerr=e)') + +def tornado(ax): + y = np.arange(8) + x1 = y + np.random.random(8) + 1 + x2 = y + 3 * np.random.random(8) + 1 + ax.barh(y, x1, color='lightblue') + ax.barh(y, -x2, color='salmon') + ax.margins(0.15) + example_utils.label(ax, 'barh(x, y)') + +def general(ax): + num = 10 + left = np.random.randint(0, 10, num) + bottom = np.random.randint(0, 10, num) + width = np.random.random(num) + 0.5 + height = np.random.random(num) + 0.5 + ax.bar(left, height, width, bottom, color='salmon') + ax.margins(0.15) + example_utils.label(ax, 'bar(l, h, w, b)') + +main() diff --git a/examples/contour_example.py b/examples/contour_example.py new file mode 100644 index 0000000..c443407 --- /dev/null +++ b/examples/contour_example.py @@ -0,0 +1,26 @@ +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.cbook import get_sample_data + +import example_utils + +z = np.load(get_sample_data('axes_grid/bivariate_normal.npy')) + +fig, axes = example_utils.setup_axes() + +axes[0].contour(z, cmap='gist_earth') +example_utils.label(axes[0], 'contour') + +axes[1].contourf(z, cmap='gist_earth') +example_utils.label(axes[1], 'contourf') + +axes[2].contourf(z, cmap='gist_earth') +cont = axes[2].contour(z, colors='black') +axes[2].clabel(cont, fontsize=6) +example_utils.label(axes[2], 'contourf + contour\n + clabel') + +example_utils.title(fig, '"contour, contourf, clabel": Contour/label 2D data', + y=0.96) +fig.savefig('contour_example.png', facecolor='none') + +plt.show() diff --git a/examples/example_utils.py b/examples/example_utils.py new file mode 100644 index 0000000..a6931cd --- /dev/null +++ b/examples/example_utils.py @@ -0,0 +1,23 @@ +""" +Just a few functions shared between all the examples. Ensures example plots are +all the same size, etc. +""" +import matplotlib.pyplot as plt + +def setup_axes(): + fig, axes = plt.subplots(ncols=3, figsize=(6.5,3)) + for ax in fig.axes: + ax.set(xticks=[], yticks=[]) + fig.subplots_adjust(wspace=0, left=0, right=0.93) + return fig, axes + +def title(fig, text, y=0.9): + fig.suptitle(text, size=14, y=y, weight='semibold', x=0.98, ha='right', + bbox=dict(boxstyle='round', fc='floralwhite', ec='#8B7E66', + lw=2)) + +def label(ax, text, y=0): + ax.annotate(text, xy=(0.5, 0.00), xycoords='axes fraction', ha='center', + style='italic', + bbox=dict(boxstyle='round', facecolor='floralwhite', + ec='#8B7E66')) diff --git a/examples/fill_example.py b/examples/fill_example.py new file mode 100644 index 0000000..207b650 --- /dev/null +++ b/examples/fill_example.py @@ -0,0 +1,77 @@ +""" +Illustrate different ways of using the various fill functions. +""" +import numpy as np +import matplotlib.pyplot as plt + +import example_utils + +def main(): + fig, axes = example_utils.setup_axes() + + fill_example(axes[0]) + fill_between_example(axes[1]) + stackplot_example(axes[2]) + + example_utils.title(fig, 'fill/fill_between/stackplot: Filled polygons', + y=0.95) + fig.savefig('fill_example.png', facecolor='none') + plt.show() + +def fill_example(ax): + # Use fill when you want a simple filled polygon between vertices + x, y = fill_data() + ax.fill(x, y, color='lightblue') + ax.margins(0.1) + example_utils.label(ax, 'fill') + +def fill_between_example(ax): + # Fill between fills between two curves or a curve and a constant value + # It can be used in several ways. We'll illustrate a few below. + x, y1, y2 = sin_data() + + # The most basic (and common) use of fill_between + err = np.random.rand(x.size)**2 + 0.1 + y = 0.7 * x + 2 + ax.fill_between(x, y + err, y - err, color='orange') + + # Filling between two curves with different colors when they cross in + # different directions + ax.fill_between(x, y1, y2, where=y1>y2, color='lightblue') + ax.fill_between(x, y1, y2, where=y10, color='red', alpha=0.5) + ax.fill_betweenx(x, -y1, where=y1<0, color='blue', alpha=0.5) + + ax.margins(0.15) + example_utils.label(ax, 'fill_between/x') + +def stackplot_example(ax): + # Stackplot is equivalent to a series of ax.fill_between calls + x, y = stackplot_data() + ax.stackplot(x, y.cumsum(axis=0), alpha=0.5) + example_utils.label(ax, 'stackplot') + +#-- Data generation ---------------------- + +def stackplot_data(): + x = np.linspace(0, 10, 100) + y = np.random.normal(0, 1, (5, 100)) + y = y.cumsum(axis=1) + y -= y.min(axis=0, keepdims=True) + return x, y + +def sin_data(): + x = np.linspace(0, 10, 100) + y = np.sin(x) + y2 = np.cos(x) + return x, y, y2 + +def fill_data(): + t = np.linspace(0, 2*np.pi, 100) + r = np.random.normal(0, 1, 100).cumsum() + r -= r.min() + return r * np.cos(t), r * np.sin(t) + +main() diff --git a/examples/imshow_example.py b/examples/imshow_example.py new file mode 100644 index 0000000..87f5561 --- /dev/null +++ b/examples/imshow_example.py @@ -0,0 +1,45 @@ +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.cbook import get_sample_data +from mpl_toolkits import axes_grid1 + +import example_utils + +def main(): + fig, axes = setup_axes() + plot(axes, *load_data()) + example_utils.title(fig, '"ax.imshow(data, ...)": Colormapped or RGB arrays') + fig.savefig('imshow_example.png', facecolor='none') + plt.show() + +def plot(axes, img_data, scalar_data, ny): + # Note: I'm defining the extent so I can cheat a bit when using ImageGrid + # to make all of the axes the same height... + + # Default: Linear interpolation + axes[0].imshow(scalar_data, cmap='gist_earth', extent=[0, ny, ny, 0]) + + # Use nearest interpolation instead. + axes[1].imshow(scalar_data, cmap='gist_earth', interpolation='nearest', + extent=[0, ny, ny, 0]) + + # Show RGB/RGBA data instead of colormapping a scalar. + axes[2].imshow(img_data) + +def load_data(): + img_data = plt.imread(get_sample_data('grace_hopper.png')) + ny, nx, nbands = img_data.shape + scalar_data = np.load(get_sample_data('axes_grid/bivariate_normal.npy')) + return img_data, scalar_data, ny + +def setup_axes(): + # We'll set up the axes a bit differently here so that they'll all be the + # same height even though the aspect will be set and adjustable is "box". + fig = plt.figure(figsize=(6,3)) + axes = axes_grid1.ImageGrid(fig, [0, 0, .93, 1], (1, 3), axes_pad=0) + + for ax in axes: + ax.set(xticks=[], yticks=[]) + return fig, axes + +main() diff --git a/examples/pcolor_example.py b/examples/pcolor_example.py new file mode 100644 index 0000000..85468b2 --- /dev/null +++ b/examples/pcolor_example.py @@ -0,0 +1,42 @@ +""" +Shows the basics of pcolor/pcolormesh. +One note: Use imshow if your data is on a rectangular grid, as it's much +faster. This example shows a case that imshow can't handle. +""" +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.cbook import get_sample_data + +import example_utils + +# Set up our data... +z = np.load(get_sample_data('axes_grid/bivariate_normal.npy')) +ny, nx = z.shape +y, x = np.mgrid[:ny, :nx] +y = (y - y.mean()) * (x + 10)**2 + +mask = (z > -0.1) & (z < 0.1) +z2 = np.ma.masked_where(mask, z) + +fig, axes = example_utils.setup_axes() + +# Either pcolor or pcolormesh would produce the same result here. +# pcolormesh is faster, however. +axes[0].pcolor(x, y, z, cmap='gist_earth') +example_utils.label(axes[0], 'either') + +# The difference between the two will become clear as we turn on edges: + +# pcolor will completely avoid drawing masked cells... +axes[1].pcolor(x, y, z2, cmap='gist_earth', edgecolor='black') +example_utils.label(axes[1], 'pcolor(x,y,z)') + +# While pcolormesh will draw them as empty (but still present) cells. +axes[2].pcolormesh(x, y, z2, cmap='gist_earth', edgecolor='black', lw=0.5, + antialiased=True) +example_utils.label(axes[2], 'pcolormesh(x,y,z)') + +example_utils.title(fig, 'pcolor/pcolormesh: Colormapped 2D arrays') +fig.savefig('pcolor_example.png', facecolor='none') + +plt.show() diff --git a/examples/plot_example.py b/examples/plot_example.py new file mode 100644 index 0000000..3a56ef3 --- /dev/null +++ b/examples/plot_example.py @@ -0,0 +1,27 @@ +import numpy as np +import matplotlib.pyplot as plt + +import example_utils + +x = np.linspace(0, 10, 100) + +fig, axes = example_utils.setup_axes() +for ax in axes: + ax.margins(y=0.10) + +# Default plotting, colors will be determined by the axes' color_cycle +for i in range(1, 6): + axes[0].plot(x, i * x) + +# Demonstrating different linestyles +for i, ls in enumerate(['-', '--', ':', '-.']): + axes[1].plot(x, np.cos(x) + i, linestyle=ls) + +# Using linestyles and markers +for i, (ls, mk) in enumerate(zip(['', '-', ':'], ['o', '^', 's'])): + axes[2].plot(x, np.cos(x) + i * x, linestyle=ls, marker=mk, markevery=10) + +example_utils.title(fig, '"ax.plot(x, y, ...)": Lines and/or markers', y=0.95) +fig.savefig('plot_example.png', facecolor='none') + +plt.show() diff --git a/examples/scatter_example.py b/examples/scatter_example.py new file mode 100644 index 0000000..33a4848 --- /dev/null +++ b/examples/scatter_example.py @@ -0,0 +1,30 @@ +""" +Illustrates the basics of using "scatter". +""" +import numpy as np +import matplotlib.pyplot as plt + +import example_utils + +# Generate some random data... +np.random.seed(1874) +x, y, z = np.random.normal(0, 1, (3, 100)) +t = np.arctan2(y, x) +size = 50 * np.cos(2 * t)**2 + 10 + +fig, axes = example_utils.setup_axes() + +axes[0].scatter(x, y, marker='o', facecolor='white', s=80) +example_utils.label(axes[0], 'scatter(x, y)') + +axes[1].scatter(x, y, s=size, marker='s', color='darkblue') +example_utils.label(axes[1], 'scatter(x, y, s)') + +axes[2].scatter(x, y, c=z, s=size, cmap='gist_ncar') +example_utils.label(axes[2], 'scatter(x, y, s, c)') + +example_utils.title(fig,'"ax.scatter(...)": Colored/scaled markers', + y=0.95) +fig.savefig('scatter_example.png', facecolor='none') + +plt.show() diff --git a/examples/statistical_example.py b/examples/statistical_example.py new file mode 100644 index 0000000..f3e46a5 --- /dev/null +++ b/examples/statistical_example.py @@ -0,0 +1,77 @@ +""" +Matplotlib has a handful of specalized statistical plotting methods. + +For many statistical plots, you may find that a specalized statistical plotting +package such as Seaborn (which uses matplotlib behind-the-scenes) is a better +fit to your needs. +""" +import numpy as np +import matplotlib.pyplot as plt + +import example_utils + +def main(): + colors = ['cyan', 'red', 'blue', 'green', 'purple'] + dists = generate_data() + + fig, axes = example_utils.setup_axes() + hist(axes[0], dists, colors) + boxplot(axes[1], dists, colors) + violinplot(axes[2], dists, colors) + + example_utils.title(fig, 'hist/boxplot/violinplot: Stastical plotting', + y=0.9) + fig.savefig('statistical_example.png', facecolor='none') + + plt.show() + +def generate_data(): + means = [0, -1, 2.5, 4.3, -3.6] + sigmas = [1.2, 5, 3, 1.5, 2] + # Each distribution has a different number of samples. + nums = [150, 1000, 100, 200, 500] + + dists = [np.random.normal(*args) for args in zip(means, sigmas, nums)] + return dists + +def hist(ax, dists, colors): + # We could call "ax.hist(dists, ...)" and skip the loop, but we'll plot + # each distribution separately so they'll overlap and turn on transparency + ax.set_color_cycle(colors) + for dist in dists: + ax.hist(dist, bins=20, normed=True, edgecolor='none', alpha=0.5) + + ax.margins(y=0.05) + ax.set_ylim(bottom=0) + + example_utils.label(ax, 'ax.hist(dists)') + +def boxplot(ax, dists, colors): + result = ax.boxplot(dists, patch_artist=True, notch=True, vert=False) + + for box, color in zip(result['boxes'], colors): + box.set(facecolor=color, alpha=0.5) + for item in ['whiskers', 'caps', 'medians']: + plt.setp(result[item], color='gray', linewidth=1.5) + plt.setp(result['fliers'], markeredgecolor='gray', markeredgewidth=1.5) + plt.setp(result['medians'], color='black') + + ax.margins(0.05) + ax.set(yticks=[], ylim=[0, 6]) + + example_utils.label(ax, 'ax.boxplot(dists)') + +def violinplot(ax, dists, colors): + result = ax.violinplot(dists, vert=False, showmedians=True) + for body, color in zip(result['bodies'], colors): + body.set(facecolor=color, alpha=0.5) + for item in ['cbars', 'cmaxes', 'cmins', 'cmedians']: + plt.setp(result[item], edgecolor='gray', linewidth=1.5) + plt.setp(result['cmedians'], edgecolor='black') + + ax.margins(0.05) + ax.set(ylim=[0, 6]) + + example_utils.label(ax, 'ax.violinplot(dists)') + +main() diff --git a/examples/vector_example.py b/examples/vector_example.py new file mode 100644 index 0000000..05c3d53 --- /dev/null +++ b/examples/vector_example.py @@ -0,0 +1,39 @@ +import matplotlib.pyplot as plt +import numpy as np + +import example_utils + +# Generate data +n = 256 +x = np.linspace(-3, 3, n) +y = np.linspace(-3, 3, n) +xi, yi = np.meshgrid(x, y) +z = (1 - xi / 2 + xi**5 + yi**3) * np.exp(-xi**2 - yi**2) +dy, dx = np.gradient(z) +mag = np.hypot(dx, dy) + +fig, axes = example_utils.setup_axes() + +# Use ax.arrow to plot a single arrow on the axes. +axes[0].arrow(0, 0, -0.5, 0.5, width=0.005, color='black') +axes[0].axis([-1, 1, -1, 1]) +example_utils.label(axes[0], 'arrow(x, y, dx, dy)') + +# Plot a regularly-sampled vector field with ax.quiver +ds = np.s_[::16, ::16] # Downsample our array a bit... +axes[1].quiver(xi[ds], yi[ds], dx[ds], dy[ds], z[ds], cmap='gist_earth', + width=0.01, scale=0.25, pivot='middle') +axes[1].axis('tight') +example_utils.label(axes[1], 'quiver(x, y, dx, dy)') + +# Use ax.streamplot to show flowlines through our vector field +# We'll get fancy and vary their width and color +lw = 2 * (mag - mag.min()) / mag.ptp() + 0.2 +axes[2].streamplot(xi, yi, dx, dy, color=z, density=1.5, linewidth=lw, + cmap='gist_earth') +example_utils.label(axes[2], 'streamplot(x, y, dx, dy)') + +example_utils.title(fig, '"arrow/quiver/streamplot": Vector fields', y=0.96) +fig.savefig('vector_example.png', facecolor='none') + +plt.show() diff --git a/exercises/2.1-bar_and_fill_between.py b/exercises/2.1-bar_and_fill_between.py new file mode 100644 index 0000000..5ca04cd --- /dev/null +++ b/exercises/2.1-bar_and_fill_between.py @@ -0,0 +1,24 @@ +import numpy as np +import matplotlib.pyplot as plt +np.random.seed(1) + +# Generate data... +y_raw = np.random.randn(1000).cumsum() + 15 +x_raw = np.linspace(0, 24, y_raw.size) + +# Get averages of every 100 samples... +x_pos = x_raw.reshape(-1, 100).min(axis=1) +y_avg = y_raw.reshape(-1, 100).mean(axis=1) +y_err = y_raw.reshape(-1, 100).ptp(axis=1) + +bar_width = x_pos[1] - x_pos[0] + +# Make a made up future prediction with a fake confidence +x_pred = np.linspace(0, 30) +y_max_pred = y_avg[0] + y_err[0] + 2.3 * x_pred +y_min_pred = y_avg[0] - y_err[0] + 1.2 * x_pred + +# Just so you don't have to guess at the colors... +barcolor, linecolor, fillcolor = 'wheat', 'salmon', 'lightblue' + +# Now you're on your own! diff --git a/exercises/2.2-vmin_vmax_imshow_and_colorbars.py b/exercises/2.2-vmin_vmax_imshow_and_colorbars.py new file mode 100644 index 0000000..4922fb3 --- /dev/null +++ b/exercises/2.2-vmin_vmax_imshow_and_colorbars.py @@ -0,0 +1,15 @@ +import numpy as np +import matplotlib.pyplot as plt +np.random.seed(1) + +# Generate random data with different ranges... +data1 = np.random.random((10, 10)) +data2 = 2 * np.random.random((10, 10)) +data3 = 3 * np.random.random((10, 10)) + +# Set up our figure and axes... +fig, axes = plt.subplots(ncols=3, figsize=plt.figaspect(0.5)) +fig.tight_layout() # Make the subplots fill up the figure a bit more... +cax = fig.add_axes([0.25, 0.1, 0.55, 0.03]) # Add an axes for the colorbar + +# Now you're on your own! diff --git a/exercises/2.1-legends_and_scaling.py b/exercises/4.1-legends_and_scaling.py similarity index 85% rename from exercises/2.1-legends_and_scaling.py rename to exercises/4.1-legends_and_scaling.py index 8d200f9..a413272 100644 --- a/exercises/2.1-legends_and_scaling.py +++ b/exercises/4.1-legends_and_scaling.py @@ -1,7 +1,7 @@ import numpy as np import matplotlib.pyplot as plt -# Try to reproduce the figure shown in images/exercise_1-2.png +# Try to reproduce the figure shown in images/exercise_4-1.png # Here's the data and colors used. t = np.linspace(0, 2 * np.pi, 150) diff --git a/exercises/2.2-spines_ticks_and_subplot_spacing.py b/exercises/4.2-spines_ticks_and_subplot_spacing.py similarity index 78% rename from exercises/2.2-spines_ticks_and_subplot_spacing.py rename to exercises/4.2-spines_ticks_and_subplot_spacing.py index d8133aa..2f607c0 100644 --- a/exercises/2.2-spines_ticks_and_subplot_spacing.py +++ b/exercises/4.2-spines_ticks_and_subplot_spacing.py @@ -1,7 +1,7 @@ import matplotlib.pyplot as plt import numpy as np -# Try to reproduce the figure shown in images/exercise_1.3.png +# Try to reproduce the figure shown in images/exercise_4.2.png # This one is a bit trickier! # Here's the data... diff --git a/exercises/4.1-goldstar.py b/exercises/5.1-goldstar.py similarity index 100% rename from exercises/4.1-goldstar.py rename to exercises/5.1-goldstar.py diff --git a/images/bar_example.png b/images/bar_example.png new file mode 100644 index 0000000..8aebe55 Binary files /dev/null and b/images/bar_example.png differ diff --git a/images/contour_example.png b/images/contour_example.png new file mode 100644 index 0000000..7e0ead7 Binary files /dev/null and b/images/contour_example.png differ diff --git a/images/exercise_2.1-bar_and_fill_between.png b/images/exercise_2.1-bar_and_fill_between.png new file mode 100644 index 0000000..37ef247 Binary files /dev/null and b/images/exercise_2.1-bar_and_fill_between.png differ diff --git a/images/exercise_2.2-vmin_vmax_imshow_and_colorbars.png b/images/exercise_2.2-vmin_vmax_imshow_and_colorbars.png new file mode 100644 index 0000000..66aaa3e Binary files /dev/null and b/images/exercise_2.2-vmin_vmax_imshow_and_colorbars.png differ diff --git a/images/exercise_2-1.png b/images/exercise_4-1.png similarity index 100% rename from images/exercise_2-1.png rename to images/exercise_4-1.png diff --git a/images/exercise_2-2.png b/images/exercise_4-2.png similarity index 100% rename from images/exercise_2-2.png rename to images/exercise_4-2.png diff --git a/images/fill_example.png b/images/fill_example.png new file mode 100644 index 0000000..1d60c0c Binary files /dev/null and b/images/fill_example.png differ diff --git a/images/imshow_example.png b/images/imshow_example.png new file mode 100644 index 0000000..6306f36 Binary files /dev/null and b/images/imshow_example.png differ diff --git a/images/pcolor_example.png b/images/pcolor_example.png new file mode 100644 index 0000000..ab3a8f5 Binary files /dev/null and b/images/pcolor_example.png differ diff --git a/images/plot_example.png b/images/plot_example.png new file mode 100644 index 0000000..afbc85e Binary files /dev/null and b/images/plot_example.png differ diff --git a/images/scatter_example.png b/images/scatter_example.png new file mode 100644 index 0000000..1f38270 Binary files /dev/null and b/images/scatter_example.png differ diff --git a/images/statistical_example.png b/images/statistical_example.png new file mode 100644 index 0000000..02ee030 Binary files /dev/null and b/images/statistical_example.png differ diff --git a/images/vector_example.png b/images/vector_example.png new file mode 100644 index 0000000..3b99d73 Binary files /dev/null and b/images/vector_example.png differ diff --git a/solutions/2.1-bar_and_fill_between.py b/solutions/2.1-bar_and_fill_between.py new file mode 100644 index 0000000..125de02 --- /dev/null +++ b/solutions/2.1-bar_and_fill_between.py @@ -0,0 +1,37 @@ +import numpy as np +import matplotlib.pyplot as plt +np.random.seed(1) + +# Generate data... +y_raw = np.random.randn(1000).cumsum() + 15 +x_raw = np.linspace(0, 24, y_raw.size) + +# Get averages of every 100 samples... +x_pos = x_raw.reshape(-1, 100).min(axis=1) +y_avg = y_raw.reshape(-1, 100).mean(axis=1) +y_err = y_raw.reshape(-1, 100).ptp(axis=1) + +bar_width = x_pos[1] - x_pos[0] + +# Make a made up future prediction with a fake confidence +x_pred = np.linspace(0, 30) +y_max_pred = y_avg[0] + y_err[0] + 2.3 * x_pred +y_min_pred = y_avg[0] - y_err[0] + 1.2 * x_pred + +# Just so you don't have to guess at the colors... +barcolor, linecolor, fillcolor = 'wheat', 'salmon', 'lightblue' + +# Now you're on your own! + +fig, ax = plt.subplots() + +ax.plot(x_raw, y_raw, color=linecolor) +ax.bar(x_pos, y_avg, width=bar_width, color=barcolor, yerr=y_err, + ecolor='gray', edgecolor='gray') +ax.fill_between(x_pred, y_min_pred, y_max_pred, color=fillcolor) + +ax.set(title='Future Projection of Attitudes', + ylabel='Snarkiness (snark units)', + xlabel='Minutes since class began') + +plt.show() diff --git a/solutions/2.2-vmin_vmax_imshow_and_colorbars.py b/solutions/2.2-vmin_vmax_imshow_and_colorbars.py new file mode 100644 index 0000000..0629513 --- /dev/null +++ b/solutions/2.2-vmin_vmax_imshow_and_colorbars.py @@ -0,0 +1,20 @@ +import numpy as np +import matplotlib.pyplot as plt +np.random.seed(1) + +# Generate random data with different ranges... +data1 = np.random.random((10, 10)) +data2 = 2 * np.random.random((10, 10)) +data3 = 3 * np.random.random((10, 10)) + +# Set up our figure and axes... +fig, axes = plt.subplots(ncols=3, figsize=plt.figaspect(0.5)) +fig.tight_layout() # Make the subplots fill up the figure a bit more... +cax = fig.add_axes([0.25, 0.1, 0.55, 0.03]) # Add an axes for the colorbar + +# Now you're on your own! +for ax, data in zip(axes, [data1, data2, data3]): + im = ax.imshow(data, vmin=0, vmax=3, interpolation='nearest') + +fig.colorbar(im, cax=cax, orientation='horizontal') +plt.show() diff --git a/solutions/2.1-legends_and_scaling.py b/solutions/4.1-legends_and_scaling.py similarity index 100% rename from solutions/2.1-legends_and_scaling.py rename to solutions/4.1-legends_and_scaling.py diff --git a/solutions/2.2-spines_ticks_and_subplot_spacing.py b/solutions/4.2-spines_ticks_and_subplot_spacing.py similarity index 100% rename from solutions/2.2-spines_ticks_and_subplot_spacing.py rename to solutions/4.2-spines_ticks_and_subplot_spacing.py diff --git a/solutions/4.1-goldstar.py b/solutions/5.1-goldstar.py similarity index 100% rename from solutions/4.1-goldstar.py rename to solutions/5.1-goldstar.py