{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "How to Python Like a Boss\n", "=============\n", "## Anaconda & Scipy for data analysis\n", "\n", "![](files/likeaboss.jpg)\n", "\n", "## [Clayton Davis](//clayadavis.net) ([@clayadavis](//twitter.com/clayadavis))\n", "### NaN group meeting, Indiana University, 23 Sep 2013\n", "\n", "[GitHub Source](https://github.com/clayadavis/python-like-a-boss)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#A note before we begin\n", "\n", "### This is a reveal.js presentation. Move within sections using the up and down buttons/keys, and between sections with left and right. I'd hate for you to miss any of this wonderful content!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#In short:\n", "\n", "1. Use a Python distribution\n", "2. Use IPython + notebook\n", "3. Use the Scipy stack" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# But why Python?\n", "\n", "* It's the best thing ever" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#No, seriously\n", "\n", "* Expressive language with easy-to-read syntax makes it easier to share and reuse code\n", "* Large ecosystem of high-quality modules makes it easy to not reinvent the wheel" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# 1. Use a Python Distribution" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "No, scratch that..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# 1. Use *Anaconda* Python Distribution\n", "\n", "[http://continuum.io/downloads](http://continuum.io/downloads)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Convenience\n", "\n", "* Many popular packages for science and data analysis preinstalled" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Portability\n", "\n", "* Use *your* version and *your* packages on any campus machine\n", " * The Simpsons (CNetS)\n", " * FutureGrid\n", " * Big Red II\n", "* Default Python installs on these machines are out of date" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Compatibility\n", "* Fix the \"Python Packaging Problem\" with dependency resolution\n", "* Anaconda uses **`conda`** as its package manager, instead of `pip` or `easy_install`\n", "* Use separate environments for incompatible packages" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Shareability\n", "\n", "* Freeze the requirements for a particular package or script\n", " * Share the requirements as dependencies\n", " * If using Anaconda, share the entire environment" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#DEMOS\n", "\n", "\n", "* Installing and updating Anaconda\n", "* Installing packages with `conda` and `pip`\n", "* Using `conda` for package environments\n", "\n", "Docs can be found [online](http://docs.continuum.io/conda/index.html).\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Installing and updating Anaconda\n", "**This works on campus machines**\n", "\n", "Find the correct link at [http://continuum.io/downloads](http://continuum.io/downloads) then type something like the following in your command shell:\n", "
\n", " wget <copy-paste that link>\n", " bash Anaconda-<your version>.sh\n", "\n", " \n", "Answer yes at the prompts. At the end, the installer asks if you want to add Anaconda to your `PATH`, say yes if this will be your primary Python install.\n", " " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To update all of anaconda's packages at once:\n", "\n", " conda update anaconda" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Installing packages with `conda` and `pip`\n", "\n", "Conda is preferable since it does dependency resolution:\n", "\n", " conda install pymc" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "But not all packages are in the conda repositories\n", " \n", " conda install geopy\n", "\n", "In that case, use `pip`\n", "\n", " pip install geopy" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Using `conda` for package environments\n", "\n", "The current version of NetworkX is 1.8.1, but suppose I have a script that is dependent on NetworkX 1.7 for now. This calls for package environments!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "* Create a new environment named \"nx1.7\", and link all the Anaconda packages\n", "\n", " conda create -n nx1.7 anaconda\n", " \n", "* List all currently-defined environments:\n", "\n", " conda info -e\n", " \n", "* Activate our new environment:\n", "\n", " source activate nx1.7\n", " \n", "* Replace NetworkX 1.8 with 1.7:\n", " \n", " conda install networkx=1.7\n", " \n", "* Deactivate our new environment, returning to the base Anaconda env:\n", "\n", " source deactivate nx1.7" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Environments are also a great way to have Python 2.7 and 3.3 side-by-side:\n", "\n", " conda create -n py3.3 python=3.3 anaconda\n", " \n", "Then, like before, I can just switch to py3k with a\n", "\n", " source activate py3.3\n", " \n", "and switch back with\n", "\n", " source deactivate py3.3" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#2. Use IPython\n", "\n", "![](files/ipython.png)\n", "\n", "[Link](http://ipython.org/)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#2.1 IPython shell\n", "\n", "* Enhanced Python shell\n", "* Comes in console and Qt versions\n", "* Awesome features\n", " * Tab-completion\n", " * Magic (special %-prefixed commands)\n", " * Inline plots in Qt console" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#IPython magic" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import random as rd\n", "import numpy as np" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit a = [rd.random() for x in range(1000)]" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "10000 loops, best of 3: 102 \u00b5s per loop\n" ] } ], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit a = [np.random.random() for x in range(1000)]" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "10000 loops, best of 3: 182 \u00b5s per loop\n" ] } ], "prompt_number": 3 }, { "cell_type": "code", "collapsed": false, "input": [ "%timeit a = np.random.random(1000)" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100000 loops, best of 3: 14 \u00b5s per loop\n" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There are also cell magics for use in IPython notebook" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%time\n", "# This is a terrible way to do this\n", "fib = [0, 1]\n", "for i in range(10**5):\n", " fib.append(fib[-1] + fib[-2])" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "CPU times: user 208 ms, sys: 24 ms, total: 232 ms\n", "Wall time: 210 ms\n" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#DEMO Qt console\n", "\n", "Run the following:\n", "
\n", " ipython qtconsole --pylab inline\n", "\n", " \n", "then paste this in the Qt console:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from scipy.special import jn\n", "x = linspace(0, 4*pi)\n", "for i in range(6):\n", " plot(x, jn(i, x))" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\n", "text": [ "
\n", " ipython notebook --pylab inline\n", "\n", "\n", "* Evaluate and edit code by the chunk (cell) instead of by line\n", "* Keep images/plots/calculations inline with code\n", "* Excellent for interactive/iterative data exploration\n", "* Use markdown instead of comments for literate programming" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#DEMO IPython Notebook\n", "\n", "If you're reading this, you're seeing my slides online. It's hard for me to demo this for you, but luckily there are [writeups](http://opentechschool.github.io/python-data-intro/core/notebook.html) and [screencasts](http://www.youtube.com/watch?v=H6dLGQw9yFQ) out there of how awesome IPython notebook is.\n", "\n", "![](files/likeaboss2.jpg)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Bonus: NBconvert\n", "\n", "* Converts notebooks into a variety of formats\n", " * LaTeX/pdf\n", " * HTML\n", " * **Reveal.js**\n", "* This entire presentation was made with IPython notebook! [GitHub Source](https://github.com/clayadavis/python-like-a-boss)\n", "* Notebooks can then be hosted/shared with [NBviewier](http://nbviewer.ipython.org/urls/raw.github.com/jrjohansson/qutip-lectures/master/Lecture-1-Jaynes-Cumming-model.ipynb) or [Wakari](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Extra Bonus: Python + JavaScript in the notebook\n", "\n", "Run [this notebook](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis) in Wakari to see Python + JavaScript in action\n", "\n", "[![](files/like-a-boss1.jpg)](https://www.wakari.io/sharing/bundle/wakari_demo/realtime_twitter_analysis)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#3. Use the SciPy stack" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Actually..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "#3. Use *the rest of* the SciPy stack\n", "\n", "![](files/scipy.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# 3.1 Numpy\n", "\n", "* Used for n-dimensional arrays\n", "* C code under the hood, so it's *really* fast when used correctly\n", "* Use it to replace **MATLAB/Octave**\n", "\n", "[Link](http://www.numpy.org/)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# Example\n", "The \"native\" Python solution for matrices is often to use a list of lists, but this can be really awful. \n", "\n", "For example, let's look at column-wise operations on a list of lists." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import random as rd\n", "N = 4\n", "\n", "lol = [[rd.random() for c in range(N)] for r in range(N)]\n", "# OR\n", "lol = []\n", "for r in range(N):\n", " row = []\n", " for c in range(N):\n", " row.append(rd.random())\n", " lol.append(row)\n", "lol" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 53, "text": [ "[[0.9937229473980533,\n", " 0.995334868014186,\n", " 0.5942674962738761,\n", " 0.5154385022192677],\n", " [0.422784005229769,\n", " 0.7807343114323023,\n", " 0.09179473422846407,\n", " 0.609573372880339],\n", " [0.4972764651566518,\n", " 0.13311678867268917,\n", " 0.12249203373176598,\n", " 0.8453804747179231],\n", " [0.15205034547325147,\n", " 0.6133030575174816,\n", " 0.9485418183964225,\n", " 0.8287048466130321]]" ] } ], "prompt_number": 53 }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "List slicing: Can we get the first column of this \"matrix?\"?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "lol[:,0]" ], "language": "python", "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "list indices must be integers, not tuple", "output_type": "pyerr", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m