From a1e4e9bb5eb71075d73c39e916e6eba3e7b94ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Tue, 16 Feb 2016 21:40:20 +0100 Subject: [PATCH] First notebook added: matplotlib --- .gitignore | 3 + LICENSE | 191 ++++++- README.md | 12 + index.ipynb | 38 ++ requirements.txt | 12 + requirements_macosx.txt | 12 + tools_matplotlib.ipynb | 1089 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 1340 insertions(+), 17 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 index.ipynb create mode 100644 requirements.txt create mode 100644 requirements_macosx.txt create mode 100644 tools_matplotlib.ipynb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24198a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.ipynb_checkpoints +my_*.png +my_*.mp4 diff --git a/LICENSE b/LICENSE index 7325a1d..4909afd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,178 @@ -The MIT License (MIT) + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Copyright (c) 2016 Aurélien Geron + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed3391c --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +Machine Learning Notebooks +========================== + +This project aims at teaching you the fundamentals of Machine Learning in +python. + +Simply open the [Jupyter](http://jupyter.org/) notebooks you are interested in: + +* within github (start at [index.ipynb](https://github.com/ageron/ml-notebooks/blob/master/index.ipynb)) +* using [Binder](http://mybinder.org/): [![Binder](http://mybinder.org/badge.svg)](http://mybinder.org/repo/ageron/ml-notebooks) +* or by cloning this repository and running Jupyter locally. + diff --git a/index.ipynb b/index.ipynb new file mode 100644 index 0000000..c3ffc6d --- /dev/null +++ b/index.ipynb @@ -0,0 +1,38 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Machine Learning Notebooks\n", + "\n", + "Welcome to the Machine Learning Notebooks.\n", + "**This work is in progress.**\n", + "\n", + "## Tools\n", + "* [Matplotlib](tools_matplotlib.ipynb)" + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d1e03c0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +jupyter +matplotlib +numpy +pandas +Pillow +scikit-learn +scipy +git+git://github.com/tensorflow/skflow.git +sympy +https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.0-py2-none-linux_x86_64.whl +wheel + diff --git a/requirements_macosx.txt b/requirements_macosx.txt new file mode 100644 index 0000000..291c806 --- /dev/null +++ b/requirements_macosx.txt @@ -0,0 +1,12 @@ +jupyter +matplotlib +numpy +pandas +Pillow +scikit-learn +scipy +git+git://github.com/tensorflow/skflow.git +sympy +https://storage.googleapis.com/tensorflow/mac/tensorflow-0.7.0-py2-none-any.whl +wheel + diff --git a/tools_matplotlib.ipynb b/tools_matplotlib.ipynb new file mode 100644 index 0000000..f2f6582 --- /dev/null +++ b/tools_matplotlib.ipynb @@ -0,0 +1,1089 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tools - matplotlib\n", + "\n", + "This notebook demonstrates how to use the matplotlib library to plot beautiful graphs." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plotting your first graph" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we need to import the `matplotlib` library." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import matplotlib" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Matplotlib can output graphs using various backend graphics libraries, such as Tk, wxPython, etc. When running python using the command line, the graphs are typically shown in a separate window. In a Jupyter notebook, we can simply output the graphs within the notebook itself by running the `%matplotlib inline` magic command." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "# matplotlib.use(\"TKAgg\") # use this instead in your program if you want to use Tk as your graphics backend." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's plot our first graph! :)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.plot([1, 2, 4, 9, 5, 3])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Yep, it's as simple as calling the `plot` function with some data, and then calling the `show` function!\n", + "\n", + "If the `plot` function is given one array of data, it will use it as the coordinates on the vertical axis, and it will just use each data point's index in the array as the horizontal coordinate.\n", + "You can also provide two arrays: one for the horizontal axis `x`, and the second for the vertical axis `y`:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "plt.plot([-3, -2, 5, 0], [1, 6, 4, 3])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The axes automatically match the extent of the data. We would like to give the graph a bit more room, so let's call the `axis` function to change the extent of each axis `[xmin, xmax, ymin, ymax]`." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot([-3, -2, 5, 0], [1, 6, 4, 3])\n", + "plt.axis([-4, 6, 0, 7])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's plot a mathematical function. We use numpy's `linspace` function to create an array `x` containing 500 floats ranging from -2 to 2, then we create a second array `y` computed as the square of `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy\n", + "x = numpy.linspace(-2, 2, 500)\n", + "y = x**2\n", + "\n", + "plt.plot(x, y)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That's a bit dry, let's add a title, and x and y labels, and draw a grid." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot(x, y)\n", + "plt.title(\"Square function\")\n", + "plt.xlabel(\"x\")\n", + "plt.ylabel(\"y = x**2\")\n", + "plt.grid(True)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Line style and color" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By default, matplotlib draws a line between consecutive points." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot([0, 100, 100, 0, 0, 100, 50, 0, 100], [0, 0, 100, 100, 0, 100, 130, 100, 0])\n", + "plt.axis([-10, 110, -10, 140])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can pass a 3rd argument to change the line's style and color.\n", + "For example `\"g--\"` means \"green dashed line\"." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot([0, 100, 100, 0, 0, 100, 50, 0, 100], [0, 0, 100, 100, 0, 100, 130, 100, 0], \"g--\")\n", + "plt.axis([-10, 110, -10, 140])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can plot multiple lines on one graph very simply: just pass `x1, y1, [style1], x2, y2, [style2], ...`\n", + "\n", + "For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot([0, 100, 100, 0, 0], [0, 0, 100, 100, 0], \"r-\", [0, 100, 50, 0, 100], [0, 100, 130, 100, 0], \"g--\")\n", + "plt.axis([-10, 110, -10, 140])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or simply call `plot` multiple times before calling `show`." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot([0, 100, 100, 0, 0], [0, 0, 100, 100, 0], \"r-\")\n", + "plt.plot([0, 100, 50, 0, 100], [0, 100, 130, 100, 0], \"g--\")\n", + "plt.axis([-10, 110, -10, 140])\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also draw simple points instead of lines. Here's an example with green dashes, red dotted line and blue triangles.\n", + "Check out [the documentation](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot) for the full list of style & color options." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 30)\n", + "plt.plot(x, x, 'g--', x, x**2, 'r:', x, x**3, 'b^')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The plot function returns a list of `Line2D` objects (one for each line). You can set extra attributes on these lines, such as the line width, the dash style or the alpha level. See the full list of attributes in [the documentation](http://matplotlib.org/users/pyplot_tutorial.html#controlling-line-properties)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 30)\n", + "line1, line2, line3 = plt.plot(x, x, 'g--', x, x**2, 'r:', x, x**3, 'b^')\n", + "line1.set_linewidth(3.0)\n", + "line1.set_dash_capstyle(\"round\")\n", + "line3.set_alpha(0.2)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Saving a figure\n", + "Saving a figure to disk is as simple as calling [`savefig`](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.savefig) with the name of the file (or a file object). The available image formats depend on the graphics backend you use." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 30)\n", + "plt.plot(x, x**2)\n", + "plt.savefig(\"my_square_function.png\", transparent=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Subplots\n", + "A matplotlib figure may contain multiple subplots. These subplots are organized in a grid. To create a subplot, just call the `subplot` function, and specify the number of rows and columns in the figure, and the index of the subplot you want to draw on (starting from 1, then left to right, and top to bottom). Note that pyplot keeps track of the currently active subplot (which you can get a reference to by calling `plt.gca()`), so when you call the `plot` function, it draws on the *active* subplot.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 30)\n", + "plt.subplot(2, 2, 1) # 2 rows, 2 columns, 1st subplot = top left\n", + "plt.plot(x, x)\n", + "plt.subplot(2, 2, 2) # 2 rows, 2 columns, 2nd subplot = top right\n", + "plt.plot(x, x**2)\n", + "plt.subplot(2, 2, 3) # 2 rows, 2 columns, 3rd subplot = bottow left\n", + "plt.plot(x, x**3)\n", + "plt.subplot(2, 2, 4) # 2 rows, 2 columns, 4th subplot = bottom right\n", + "plt.plot(x, x**4)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* Note that `subplot(223)` is a shorthand for `subplot(2, 2, 3)`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is easy to create subplots that span across multiple grid cells like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.subplot(2, 2, 1) # 2 rows, 2 columns, 1st subplot = top left\n", + "plt.plot(x, x)\n", + "plt.subplot(2, 2, 2) # 2 rows, 2 columns, 2nd subplot = top right\n", + "plt.plot(x, x**2)\n", + "plt.subplot(2, 1, 2) # 2 rows, *1* column, 2nd subplot = bottom\n", + "plt.plot(x, x**3)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need more complex subplot positionning, you can use `subplot2grid` instead of `subplot`. You specify the number of rows and columns in the grid, then your subplot's position in that grid (top-left = (0,0)), and optionally how many rows and/or columns it spans. For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.subplot2grid((3,3), (0, 0), rowspan=2, colspan=2)\n", + "plt.plot(x, x**2)\n", + "plt.subplot2grid((3,3), (0, 2))\n", + "plt.plot(x, x**3)\n", + "plt.subplot2grid((3,3), (1, 2), rowspan=2)\n", + "plt.plot(x, x**4)\n", + "plt.subplot2grid((3,3), (2, 0), colspan=2)\n", + "plt.plot(x, x**5)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need even more flexibility in subplot positioning, check out the [GridSpec documentation](http://matplotlib.org/users/gridspec.html)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Multiple figures\n", + "It is also possible to draw multiple figures. Each figure may contain one or more subplots. By default, matplotlib creates `figure(1)` automatically. When you switch figure, pyplot keeps track of the currently active figure (which you can get a reference to by calling `plt.gcf()`), and the active subplot of that figure becomes the current subplot." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 30)\n", + "\n", + "plt.figure(1)\n", + "plt.subplot(211)\n", + "plt.plot(x, x**2)\n", + "plt.title(\"Square and Cube\")\n", + "plt.subplot(212)\n", + "plt.plot(x, x**3)\n", + "\n", + "plt.figure(2, figsize=(10, 5))\n", + "plt.subplot(121)\n", + "plt.plot(x, x**4)\n", + "plt.title(\"y = x**4\")\n", + "plt.subplot(122)\n", + "plt.plot(x, x**5)\n", + "plt.title(\"y = x**5\")\n", + "\n", + "plt.figure(1) # back to figure 1, current subplot is 212 (bottom)\n", + "plt.plot(x, -x**3, \"r:\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pyplot's state machine: implicit *vs* explicit\n", + "So far we have used Pyplot's state machine which keeps track of the currently active subplot. Every time you call the `plot` function, pyplot just draws on the currently active subplot. It also does some more magic, such as automatically creating a figure and a subplot when you call `plot`, if they don't exist yet. This magic is convenient in an interactive environment (such as Jupyter).\n", + "\n", + "But when you are writing a program, *explicit is better than implicit*. Explicit code is usually easier to debug and maintain, and if you don't believe me just read the 2nd rule in the Zen of Python:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import this" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Fortunately, Pyplot allows you to ignore the state machine entirely, so you can write beautifully explicit code. Simply call the `subplots` function and use the figure object and the list of axes objects that are returned. No more magic! For example:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-2, 2, 200)\n", + "fig1, (ax_top, ax_bottom) = plt.subplots(2, 1, sharex=True)\n", + "fig1.set_size_inches(10,5)\n", + "line1, line2 = ax_top.plot(x, numpy.sin(3*x**2), \"r-\", x, numpy.cos(5*x**2), \"b-\")\n", + "line3, = ax_bottom.plot(x, numpy.sin(3*x), \"r-\")\n", + "ax_top.grid(True)\n", + "\n", + "fig2, ax = plt.subplots(1, 1)\n", + "ax.plot(x, x**2)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For consistency, we will continue to use pyplot's state machine in the rest of this tutorial, but we recommend using the object-oriented interface in your programs.\n", + "\n", + "## Pylab *vs* Pyplot *vs* Matplotlib\n", + "\n", + "There is some confusion around the relationship between pylab, pyplot and matplotlib. It's simple: matplotlib is the full library, it contains everything including pylab and pyplot.\n", + "\n", + "Pyplot provides a number of tools to plot graphs, including the state-machine interface to the underlying object-oriented plotting library.\n", + "\n", + "Pylab is a convenience module that imports matplotlib.pyplot and numpy in a single name space. You will find many examples using pylab, but it is no longer recommended (because *explicit* imports are better than *implicit* ones)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Drawing text\n", + "You can call `text` to add text at any location in the graph. Just specify the horizontal and vertical coordinates and the text, and optionally some extra attributes. Any text in matplotlib may contain TeX equation expressions, see [the documentation](http://matplotlib.org/users/mathtext.html) for more details." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.5, 1.5, 30)\n", + "px = 0.8\n", + "py = px**2\n", + "\n", + "plt.plot(x, x**2, \"b-\", px, py, \"ro\")\n", + "\n", + "plt.text(0, 1.5, \"Square function\\n$y = x^2$\", fontsize=20, color='blue', horizontalalignment=\"center\")\n", + "plt.text(px - 0.08, py, \"Beautiful point\", ha=\"right\", weight=\"heavy\")\n", + "plt.text(px, py, \"x = %0.2f\\ny = %0.2f\"%(px, py), rotation=50, color='gray')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* Note: `ha` is an alias for `horizontalalignment`\n", + "\n", + "For more text properties, visit [the documentation](http://matplotlib.org/users/text_props.html#text-properties).\n", + "\n", + "It is quite frequent to annotate elements of a graph, such as the beautiful point above. The `annotate` function makes this easy: just indicate the location of the point of interest, and the position of the text, plus optionally some extra attributes for the text and the arrow." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.plot(x, x**2, px, py, \"ro\")\n", + "plt.annotate(\"Beautiful point\", xy=(px, py), xytext=(px-1.3,py+0.5),\n", + " color=\"green\", weight=\"heavy\", fontsize=14,\n", + " arrowprops={\"facecolor\": \"lightgreen\"})\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also add a bounding box around your text by using the `bbox` attribute:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [], + "source": [ + "plt.plot(x, x**2, px, py, \"ro\")\n", + "\n", + "bbox_props = dict(boxstyle=\"rarrow,pad=0.3\", ec=\"b\", lw=2, fc=\"lightblue\")\n", + "plt.text(px-0.2, py, \"Beautiful point\", bbox=bbox_props, ha=\"right\")\n", + "\n", + "bbox_props = dict(boxstyle=\"round4,pad=1,rounding_size=0.2\", ec=\"black\", fc=\"#EEEEFF\", lw=5)\n", + "plt.text(0, 1.5, \"Square function\\n$y = x^2$\", fontsize=20, color='black', ha=\"center\", bbox=bbox_props)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Just for fun, if you want an [xkcd](http://xkcd.com)-style plot, just draw within a `with plt.xkcd()` section:" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "with plt.xkcd():\n", + " plt.plot(x, x**2, px, py, \"ro\")\n", + "\n", + " bbox_props = dict(boxstyle=\"rarrow,pad=0.3\", ec=\"b\", lw=2, fc=\"lightblue\")\n", + " plt.text(px-0.2, py, \"Beautiful point\", bbox=bbox_props, ha=\"right\")\n", + "\n", + " bbox_props = dict(boxstyle=\"round4,pad=1,rounding_size=0.2\", ec=\"black\", fc=\"#EEEEFF\", lw=5)\n", + " plt.text(0, 1.5, \"Square function\\n$y = x^2$\", fontsize=20, color='black', ha=\"center\", bbox=bbox_props)\n", + "\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Legends\n", + "The simplest way to add a legend is to set a label on all lines, then just call the `legend` function." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1.4, 1.4, 50)\n", + "plt.plot(x, x**2, \"r--\", label=\"Square function\")\n", + "plt.plot(x, x**3, \"g-\", label=\"Cube function\")\n", + "plt.legend(loc=\"best\")\n", + "plt.grid(True)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Non linear scales\n", + "Matplotlib supports non linear scales, such as logarithmic or logit scales." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "x = numpy.linspace(0.1, 15, 500)\n", + "y = x**3/numpy.exp(2*x)\n", + "\n", + "plt.figure(1)\n", + "plt.plot(x, y)\n", + "plt.yscale('linear')\n", + "plt.title('linear')\n", + "plt.grid(True)\n", + "\n", + "plt.figure(2)\n", + "plt.plot(x, y)\n", + "plt.yscale('log')\n", + "plt.title('log')\n", + "plt.grid(True)\n", + "\n", + "plt.figure(3)\n", + "plt.plot(x, y)\n", + "plt.yscale('logit')\n", + "plt.title('logit')\n", + "plt.grid(True)\n", + "\n", + "plt.figure(4)\n", + "plt.plot(x, y - y.mean())\n", + "plt.yscale('symlog', linthreshy=0.05)\n", + "plt.title('symlog')\n", + "plt.grid(True)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ticks and tickers\n", + "The axes have little marks called \"ticks\". To be precise, \"ticks\" are the *locations* of the marks (eg. (-1, 0, 1)), \"tick lines\" are the small lines drawn at those locations, \"tick labels\" are the labels drawn next to the tick lines, and \"tickers\" are objects that are capable of deciding where to place ticks. The default tickers typically do a pretty good job at placing ~5 to 8 ticks at a reasonable distance from one another.\n", + "\n", + "But sometimes you need more control (eg. there are too many tick labels on the logit graph above). Fortunately, matplotlib gives you full control over ticks. You can even activate minor ticks.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-2, 2, 100)\n", + "\n", + "plt.figure(1, figsize=(15,10))\n", + "plt.subplot(131)\n", + "plt.plot(x, x**3)\n", + "plt.grid(True)\n", + "plt.title(\"Default ticks\")\n", + "\n", + "ax = plt.subplot(132)\n", + "plt.plot(x, x**3)\n", + "ax.xaxis.set_ticks(numpy.arange(-2, 2, 1))\n", + "plt.grid(True)\n", + "plt.title(\"Manual ticks on the x-axis\")\n", + "\n", + "ax = plt.subplot(133)\n", + "plt.plot(x, x**3)\n", + "plt.minorticks_on()\n", + "ax.tick_params(axis='x', which='minor', bottom='off')\n", + "ax.xaxis.set_ticks([-2, 0, 1, 2])\n", + "ax.yaxis.set_ticks(numpy.arange(-5, 5, 1))\n", + "ax.yaxis.set_ticklabels([\"min\", -4, -3, -2, -1, 0, 1, 2, 3, \"max\"])\n", + "plt.title(\"Manual ticks and tick labels\\n(plus minor ticks) on the y-axis\")\n", + "\n", + "\n", + "plt.grid(True)\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Polar projection\n", + "Drawing a polar graph is as easy as setting the `projection` attribute to `\"polar\"` when creating the subplot." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "radius = 1\n", + "theta = numpy.linspace(0, 2*numpy.pi*radius, 1000)\n", + "\n", + "plt.subplot(111, projection='polar')\n", + "plt.plot(theta, numpy.sin(5*theta), \"g-\")\n", + "plt.plot(theta, 0.5*numpy.cos(20*theta), \"b-\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3D projection\n", + "\n", + "Plotting 3D graphs is quite straightforward. You need to import `Axes3D`, which registers the `\"3d\"` projection. Then create a subplot setting the `projection` to `\"3d\"`. This returns an `Axes3DSubplot` object, which you can use to call `plot_surface`, giving x, y, and z coordinates, plus optional attributes." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "from mpl_toolkits.mplot3d import Axes3D\n", + "\n", + "x = numpy.linspace(-5, 5, 50)\n", + "y = numpy.linspace(-5, 5, 50)\n", + "X, Y = numpy.meshgrid(x, y)\n", + "R = numpy.sqrt(X**2 + Y**2)\n", + "Z = numpy.sin(R)\n", + "\n", + "figure = plt.figure(1, figsize = (12, 4))\n", + "subplot3d = plt.subplot(111, projection='3d')\n", + "surface = subplot3d.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=matplotlib.cm.coolwarm, linewidth=0.1)\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another way to display this same data is *via* a contour plot." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "plt.contourf(X, Y, Z, cmap=matplotlib.cm.coolwarm)\n", + "plt.colorbar()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Scatter plot" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To draw a scatter plot, simply provide the x and y coordinates of the points." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from numpy.random import rand\n", + "x, y = rand(2, 100)\n", + "plt.scatter(x, y)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You may also optionally provide the scale of each point." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x, y, scale = rand(3, 100)\n", + "scale = 500 * scale ** 5\n", + "plt.scatter(x, y, s=scale)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And as usual there are a number of other attributes you can set, such as the fill and edge colors and the alpha level." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "for color in ['red', 'green', 'blue']:\n", + " n = 100\n", + " x, y = rand(2, n)\n", + " scale = 500.0 * rand(n) ** 5\n", + " plt.scatter(x, y, s=scale, c=color, alpha=0.3, edgecolors='blue')\n", + "\n", + "plt.grid(True)\n", + "\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lines" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from numpy.random import randn\n", + "x = randn(1000)\n", + "y = 3*x + 5 + randn(1000)*2\n", + "plt.axis([-2.5, 2.5, -5, 15])\n", + "plt.scatter(x, y)\n", + "plt.vlines(0, -numpy.inf, numpy.inf)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Histograms" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "data = [1, 1.1, 1.8, 2, 2.1, 3.2, 3, 3, 3, 3]\n", + "plt.subplot(211)\n", + "plt.hist(data, bins = 10, rwidth=0.8)\n", + "\n", + "plt.subplot(212)\n", + "plt.hist(data, bins = [1, 1.5, 2, 2.5, 3], rwidth=0.95)\n", + "plt.xlabel(\"Value\")\n", + "plt.ylabel(\"Frequency\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [], + "source": [ + "data1 = numpy.random.randn(400)\n", + "data2 = numpy.random.randn(500) + 3\n", + "data3 = numpy.random.randn(450) + 6\n", + "data4a = numpy.random.randn(200) + 9\n", + "data4b = numpy.random.randn(100) + 10\n", + "\n", + "plt.hist(data1, bins=5, color='g', alpha=0.75, label='bar hist') # default histtype='bar'\n", + "plt.hist(data2, color='b', alpha=0.65, histtype='stepfilled', label='stepfilled hist')\n", + "plt.hist(data3, color='r', histtype='step', label='step hist')\n", + "plt.hist((data4a, data4b), color=('r','m'), alpha=0.55, histtype='barstacked', label=('barstacked a', 'barstacked b'))\n", + "\n", + "plt.xlabel(\"Value\")\n", + "plt.ylabel(\"Frequency\")\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Animations\n", + "Although matplotlib is mostly used to generate images, it is also capable of displaying animations, depending on the Backend you use. In a Jupyter notebook, we need to use the `nbagg` backend to use interactive matplotlib features, including animations. We also need to import `matplotlib.animation`." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib nbagg\n", + "import matplotlib.animation as animation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this example, we start by creating data points, then we create an empty plot, we define the update function that will be called at every iteration of the animation, and finally we add an animation to the plot by creating a `FuncAnimation` instance.\n", + "\n", + "The `FuncAnimation` constructor takes a figure, an update function and optional arguments. We specify that we want a 100-frame long animation, with 20ms between each frame. At each iteration, `FuncAnimation` calls our update function and passes it the frame number `num` (from 0 to 99 in our case) followed by the extra arguments that we specified with `fargs`.\n", + "\n", + "Our update function simply sets the line data to be the first `num` data points (so the data gets drawn gradually), and just for fun we also add a small random number to each data point so that the line appears to wiggle." + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "x = numpy.linspace(-1, 1, 100)\n", + "y = numpy.sin(x**2*25)\n", + "data = numpy.array([x, y])\n", + "\n", + "fig = plt.figure()\n", + "line, = plt.plot([], [], \"r-\") # start with an empty plot\n", + "plt.axis([-1.1, 1.1, -1.1, 1.1])\n", + "plt.plot([-0.5, 0.5], [0, 0], \"b-\", [0, 0], [-0.5, 0.5], \"b-\", 0, 0, \"ro\")\n", + "plt.grid(True)\n", + "plt.title(\"Marvelous animation\")\n", + "\n", + "# this function will be called at every iteration\n", + "def update_line(num, data, line):\n", + " line.set_data(data[..., :num] + numpy.random.rand(2, num) / 25) # we only plot the first `num` data points.\n", + " return line,\n", + "\n", + "line_ani = animation.FuncAnimation(fig, update_line, frames=100, fargs=(data, line), interval=67)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Saving animations to video files\n", + "Matplotlib relies on 3rd-party libraries to write videos such as [FFMPEG](https://www.ffmpeg.org/) or `mencoder`. In this example we will be using FFMPEG so be sure to install it first." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Writer = animation.writers['ffmpeg']\n", + "writer = Writer(fps=15, metadata=dict(artist='Me'), bitrate=1800)\n", + "line_ani.save('my_wiggly.mp4', writer=writer)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What next?\n", + "Now you know all the basics of matplotlib, but there are many more options available. The best way to learn more, is to visit the [gallery](http://matplotlib.org/gallery.html), look at the images, choose a plot that you are interested in, then just copy the code in a Jupyter notebook and play around with it." + ] + } + ], + "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" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}