{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "# Unit 6, Lecture 3\n", "\n", "*Numerical Methods and Statistics*\n", "\n", "----\n", "\n", "#### Prof. Andrew White, Feb 22 2020" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Lecture Goals\n", "\n", "0. Know what a python function is and be able to define one\n", "1. Be able to call a function and understand how arguments are passed to the function\n", "2. Know the difference between arguments and variables\n", "3. Understand how to return values\n", "4. Be able to design and document a function\n", "5. Be able to convert a function to work with numpy" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "%matplotlib inline\n", "import matplotlib" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Defining Functions\n", "===\n", "\n", "Sometimes it's nice to use functions instead of writing the equation for a geometric distribution each time." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Function Definition\n", "====\n", "\n", "You may define your own functions using the `def` command." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n" ] } ], "source": [ "def print_hello():\n", " print('Hello')\n", "\n", "print_hello()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You may give arguments by putting them inside the `()`. Like this:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Go dog\n", "See dog go\n" ] } ], "source": [ "def print_string(s):\n", " print(s) # <--- I can now use s anywhere inside the function\n", "\n", "print_string('Go dog')\n", "print_string('See dog go')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "What if you want to return something? You can, with the `return` function." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n" ] } ], "source": [ "def square(x):\n", " return x * x\n", "\n", "x_squared = square(2)\n", "print(x_squared)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "What is the difference between returning and printing?\n", "---" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "25\n" ] }, { "ename": "TypeError", "evalue": "unsupported operand type(s) for *: 'NoneType' and 'int'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0msquare_print\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for *: 'NoneType' and 'int'" ] } ], "source": [ "def square_print(x):\n", " print(x * x)\n", "\n", "square_print(5) * 4" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "square(5) * 4" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "You can pass multple arguments and your function can be multiple lines, just like `for` loops and `if` statements." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "0.06561" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def geometric(n, p):\n", " P_n = (1 - p)**(n - 1) * p\n", " return P_n \n", "geometric(5, 0.1)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "image/png": "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\nYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "Q = np.arange(1,100)\n", "plt.plot(Q, geometric(Q, 0.1), 'o')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Documenting Your Function\n", "----\n", "\n", "You can make your own documentation. Use the `'''` instead of just one `'` so that you can use multiple lines\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def my_geom(n, p=0.5):\n", " '''This function will compute the probability of n from a geometric distribution given p\n", " \n", " Args:\n", " p: The probability of success\n", " n: The number of times before and including success\n", " \n", " returns: the probability'''\n", " return (1 - p)**(n - 1)* p" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function my_geom in module __main__:\n", "\n", "my_geom(n, p=0.5)\n", " This function will compute the probability of n from a geometric distribution given p\n", " \n", " Args:\n", " p: The probability of success\n", " n: The number of times before and including success\n", " \n", " returns: the probability\n", "\n" ] } ], "source": [ "help(my_geom)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Notice I used a default value for `p`" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "0.0625" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_geom(n=4)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Notice I used the name of the argument with the `n=4`. This is called a *named argument*. You can mix the use of named arguments and *positional arguments* interchangably. Positional arguments are just regular arguments. For example:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "0.14699999999999996" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_geom(3, p=0.3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "There is one rule though, you must put positional arguments **before** named arguments. For example, this will not work:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "ename": "SyntaxError", "evalue": "positional argument follows keyword argument (, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m my_geom(n=3, 0.2)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n" ] } ], "source": [ "my_geom(n=3, 0.2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Things to consider in creating a fucntion\n", "----\n", "\n", "1. Write the signature and doc string describing what your function should do and its input/output\n", "2. Write a function that generates correct output for most inputs\n", "3. Consider edge cases and possible user error\n", "4. Validate for numpy (optional)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Example\n", "---\n", "\n", "For our example, we'll write a function that computes the Fibonacci sequence up to the $n$th term. The Fibonacci sequence is a sequence whose $n$th element is the sum of the $n-1$ and $n-2$ elements. The first two elements are defined to be $1$. Here's the first few terms:\n", "\n", "$$\n", "1,\\,1,\\,2,\\,3,\\,5,\\,8\n", "$$\n", "\n", "So our function should return `5` if it is passed `4` (first term is indexed as `0`). " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Write doc string\n", "---" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true, "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def fib():\n", " '''Returns the ith element from the Fibonacci sequence\n", " \n", " '''" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Define the input/output\n", "----\n", "\n", "We decide only 1 input is necessary" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib(i):\n", " '''Returns the ith element from the Fibonacci sequence\n", "\n", " Args:\n", " i: the index of the element in the Fibonacci sequence \n", "\n", " returns: the element at the given index in the Fibonacci sequence\n", " '''" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Make it work\n", "---\n", "\n", "Now we actually test it out! I'll omit the docstring to make the slides easier to view. We should use inline comments with a `#` to indicate our logic in the program" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib_1(i):\n", " last = 1 # our n - 1 element\n", " last_last = 1 # our n -2 element\n", " for j in range(i): #go until we are at the ith element\n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_1(4)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "It looks pretty good! Except, it is off by 1 from our original example." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib_2(i):\n", " last = 1 # our n - 1 element\n", " last_last = 1 # our n -2 element\n", " #sub 1 because last and last_last\n", " #are set corresponding to n=2\n", " for j in range(i - 1): \n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_2(4)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_2(5)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "13" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_2(6)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Looks like it works on our original example" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Consider Edge Case\n", "---\n", "\n", "How does it deal with the starting point?" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "UnboundLocalError", "evalue": "local variable 'current' referenced before assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfib_2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mfib_2\u001b[0;34m(i)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mlast_last\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlast\u001b[0m \u001b[0;31m#our new n - 2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mlast\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcurrent\u001b[0m \u001b[0;31m# our new n - 1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mcurrent\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'current' referenced before assignment" ] } ], "source": [ "fib_2(0)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "UnboundLocalError", "evalue": "local variable 'current' referenced before assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mfib_2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mfib_2\u001b[0;34m(i)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mlast_last\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlast\u001b[0m \u001b[0;31m#our new n - 2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mlast\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcurrent\u001b[0m \u001b[0;31m# our new n - 1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mcurrent\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'current' referenced before assignment" ] } ], "source": [ "fib_2(1)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_2(2)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib_3(i):\n", " \n", " #deal with edge cases\n", " if i == 0 or i == 1:\n", " return 1\n", " \n", " last = 1 # our n - 1 element\n", " last_last = 1 # our n -2 element\n", " #sub 1 because last and last_last\n", " #are set corresponding to n=2\n", " for j in range(i - 1): \n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_3(0)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Deal with use error\n", "----\n", "\n", "Make your function easy to use by gracefully dealing with bad input conditions." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib_4(i):\n", " \n", " #check that i is valid\n", " if(type(i) != int or i < 0):\n", " return None\n", " \n", " #deal with edge cases\n", " if i == 0 or i == 1:\n", " return 1\n", " \n", " last = 1 # our n - 1 element\n", " last_last = 1 # our n -2 element\n", " #sub 1 because last and last_last\n", " #are set corresponding to n=2\n", " for j in range(i - 1): \n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "print(fib_4(-4))" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "print(fib_4('fdsa'))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "34" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_4(8)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Dealing with user error is a fascinating topic and gets into user interface design, which is covered nicely in this [introductory video](https://www.youtube.com/watch?v=r2CbbBLVaPk) from the web design community. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "How to convert a function into a numpy function\n", "====\n", "\n", "`np.vectorize(fxn)` will turn your function into a numpy version. You pass it your function (`fxn`) and it returns a new function which is yours but upgraded to work on numpy arrays." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0. 0.68163876 0.99749499 0.7780732 0.14112001]\n" ] } ], "source": [ "import numpy as np\n", "from math import sin\n", "\n", "#Don't actually do this, this is an example. Just use np.sin instead.\n", "my_np_sin = np.vectorize(sin) #<-- I'm turning the math sine into my own version\n", "\n", "x = np.linspace(0,3,5)\n", "print(my_np_sin(x))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "ValueError", "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmy_distribution\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mmy_distribution\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmy_distribution\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m'''my special snowflake distribution'''\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m40\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m0.2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" ] } ], "source": [ "def my_distribution(x):\n", " '''my special snowflake distribution'''\n", " if x > 40:\n", " return 0.2\n", " else:\n", " return 0.8\n", "\n", "x = np.linspace(0,100,10)\n", "print(my_distribution(x))" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.8 0.8 0.8 0.8 0.2 0.2 0.2 0.2 0.2 0.2]\n" ] } ], "source": [ "numpy_version_distribution = np.vectorize(my_distribution)\n", "print(numpy_version_distribution(x))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "What happened with the doc string though? You can only access it through the `np.info`, instead of `help`" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "my special snowflake distribution\n" ] } ], "source": [ "np.info(numpy_version_distribution)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is not always necessary - usually only needed when working with loops and `if` statements. " ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 2. 2.16011948 2.33305808 2.5198421 2.72158 2.93946898\n", " 3.1748021 3.42897593 3.70349885 4. ]\n" ] } ], "source": [ "def foo(x):\n", " return 2 ** x\n", "data = np.linspace(1,2,10)\n", "\n", "print(foo(data))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "Revise\n", "----\n", "\n", "It's always good to revise your functions after considering each of these aspects. Let's say we want our Fibonacci function to be capable of specifying the starting point? That would require specifying two values." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def fib_5(i, start=(1,1)):\n", " \n", " #check that i is valid\n", " if(type(i) != int or i < 0): \n", " return None\n", " \n", " #deal with edge cases\n", " if i == 0:\n", " return start[0]\n", " if i == 1:\n", " return start[1]\n", " \n", " last = start[0] # our n - 1 element\n", " last_last = start[1] # our n -2 element\n", " #sub 1 because last and last_last\n", " #are set corresponding to n=2\n", " for j in range(i - 1): \n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib_5(2, start=(1, 2))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Now we'll put it all together with numpy and the doc string" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def py_fib(i, start=(1,1)):\n", " '''Returns the nth element from the Fibonacci sequence\n", "\n", " Args:\n", " i: the index of the element in the Fibonacci sequence \n", " start: the first and second elements of the sequence. Default is 1,1\n", "\n", " returns: the element at the given index in the Fibonacci sequence\n", " '''\n", " #check that i is valid\n", " if(type(i) != int or i < 0): \n", " return None\n", " \n", " #deal with edge cases\n", " if i == 0:\n", " return start[0]\n", " if i == 1:\n", " return start[1]\n", " \n", " last = start[0] # our n - 1 element\n", " last_last = start[1] # our n -2 element\n", " #sub 1 because last and last_last\n", " #are set corresponding to n=2\n", " for j in range(i - 1): \n", " current = last + last_last #the add\n", " last_last = last #our new n - 2\n", " last = current # our new n - 1\n", " return current" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "#you can specifiy that it returns integers\n", "#to simplifiy your output\n", "fib = np.vectorize(py_fib, otypes=[np.int])" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55])" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "i = np.arange(10)\n", "fib(i)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Returns the nth element from the Fibonacci sequence\n", "\n", "Args:\n", " i: the index of the element in the Fibonacci sequence \n", " start: the first and second elements of the sequence. Default is 1,1\n", "\n", "returns: the element at the given index in the Fibonacci sequence\n" ] } ], "source": [ "np.info(fib)" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 1 }