{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "numpy.ipynb",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"
"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nbWAdu9YXQ4m",
"colab_type": "text"
},
"source": [
"##➛About this tutorial"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LsZUmB7jXQ4o",
"colab_type": "text"
},
"source": [
"Jan 17, 2020\n",
"\n",
"This Python and Numpy turorial (`part II - Numpy`) was adapted by [Badri Adhikari](https://badriadhikari.github.io/) from the original adaptation by [Volodymyr Kuleshov](http://web.stanford.edu/~kuleshov/) and [Isaac Caswell](https://symsys.stanford.edu/viewing/symsysaffiliate/21335) from the `CS231n` Python tutorial by Justin Johnson (http://cs231n.github.io/python-numpy-tutorial/). Expanded the broadcasting section by adapting [this tutorial](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1zMqcHn7XQ66",
"colab_type": "text"
},
"source": [
"##➛Introduction to Numpy\n",
"Numpy [documentation](http://docs.scipy.org/doc/numpy/reference/)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cEfvT8RkXQ66",
"colab_type": "text"
},
"source": [
"* Numpy is the **core library** for scientific computing in Python\n",
"* It provides (a) a **high-performance** multidimensional array object, and (b) **tools** for working with these arrays."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qdlv4YmgXQ67",
"colab_type": "text"
},
"source": [
"To use Numpy, we first need to import the `numpy` package:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "c0wOFMFBXQ69",
"colab_type": "code",
"colab": {}
},
"source": [
"import numpy as np"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "0Trk5i8CXQ6_",
"colab_type": "text"
},
"source": [
"##➛Arrays"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "t6wwFkbbXQ7A",
"colab_type": "text"
},
"source": [
"* A numpy array is a **grid of values, all of the \"same type\"**, and is **indexed by a tuple of nonnegative integers**. \n",
"* Numpy only supports numeric data types such as np.int8, np.int32, np.float32, np.half (float 16), etc.\n",
"* The number of dimensions is the **rank of the array**. For example an array of dimensions 2x3x4 has rank 3. \n",
"* The **shape of an array is a tuple of integers** giving the size of the array along each dimension.\n",
"* We can initialize numpy arrays from nested Python lists. For example, `x = [[2,3][4,5]]`\n",
"* Elements can be accessed using square brackets. For example, `print( x[0] )`"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "q__narZLAhKO",
"colab_type": "text"
},
"source": [
"**Caution! Python arrays and Numpy arrays are different objects!** \n",
"For example, `type` only works with Python data structures `shape` works with numpy arrays. \n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "_hQuL6DpXQ7D",
"colab_type": "code",
"outputId": "eab10e00-3139-4a23-cbc5-6e6ea788665b",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 236
}
},
"source": [
"a = np.array([1, 2, 3]) # Create a rank 1 array\n",
"print(type(a), a.shape, a[0], a[1], a[2])\n",
"a[0] = 's' # Change an element of the array\n",
"print(a) "
],
"execution_count": 90,
"outputs": [
{
"output_type": "stream",
"text": [
" (3,) 1 2 3\n"
],
"name": "stdout"
},
{
"output_type": "error",
"ename": "ValueError",
"evalue": "ignored",
"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 1\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Create a rank 1 array\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m's'\u001b[0m \u001b[0;31m# Change an element of the array\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 's'"
]
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "oZASlTtgXQ7E",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "8327ae22-3377-4f5a-f8a1-4a645015be04"
},
"source": [
"b = np.array([[1,2,3],[4,5,6]]) # Create a rank 2 array\n",
"print(b)"
],
"execution_count": 91,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1 2 3]\n",
" [4 5 6]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "gkN2Ty_HXQ7G",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "d8aa6d05-3dcc-41e3-d145-014b3be1b475"
},
"source": [
"print(b.shape)\n",
"print(b[0, 0], b[0, 1], b[1, 0])"
],
"execution_count": 92,
"outputs": [
{
"output_type": "stream",
"text": [
"(2, 3)\n",
"1 2 4\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "25aaTsbRi8JX",
"colab_type": "text"
},
"source": [
"**\"`shape`\" is your hammer!** \n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "PYoFBxSjXQ7I",
"colab_type": "text"
},
"source": [
"Numpy also provides many functions to create arrays:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "0C0jJGOJXQ7I",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "01eb29d7-ec12-417c-b993-632e69d34b43"
},
"source": [
"a = np.zeros((2,2)) # Create an array of all zeros\n",
"print(a)"
],
"execution_count": 93,
"outputs": [
{
"output_type": "stream",
"text": [
"[[0. 0.]\n",
" [0. 0.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "vVTuTelUXQ7N",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1000
},
"outputId": "7ba1d4a2-380d-41ea-ee14-a59a746c9c7a"
},
"source": [
"b = np.ones((1,2, 5, 6, 7)) # Create an array of all ones\n",
"print(b)"
],
"execution_count": 94,
"outputs": [
{
"output_type": "stream",
"text": [
"[[[[[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]]\n",
"\n",
"\n",
" [[[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]\n",
"\n",
" [[1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]\n",
" [1. 1. 1. 1. 1. 1. 1.]]]]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "Qm_CGpnTXQ7O",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "bc364006-ba61-4455-b3ad-e44b7adce926"
},
"source": [
"c = np.full((2,2), 7) # Create a constant array\n",
"print(c)"
],
"execution_count": 95,
"outputs": [
{
"output_type": "stream",
"text": [
"[[7 7]\n",
" [7 7]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "DqKBBtZSXQ7Q",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "72bc4b04-53a0-45e1-e49a-050df80bac7d"
},
"source": [
"d = np.eye(3) # Create a 2x2 identity matrix\n",
"print(d)"
],
"execution_count": 96,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1. 0. 0.]\n",
" [0. 1. 0.]\n",
" [0. 0. 1.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "9dQe4AxNXQ7U",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "d2e5581a-55b8-4d05-9fac-56eef2e782d4"
},
"source": [
"e = np.random.random((2,2)) * 100 # Create an array filled with random values\n",
"print(e)"
],
"execution_count": 97,
"outputs": [
{
"output_type": "stream",
"text": [
"[[76.37361261 20.04861709]\n",
" [97.33716423 67.42584384]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rqyR9AIGXQ7X",
"colab_type": "text"
},
"source": [
"##➛Array indexing"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nk5DA500XQ7Z",
"colab_type": "text"
},
"source": [
"* Numpy offers **several ways to index into arrays**\n",
"* **Slicing**: Similar to Python lists, numpy arrays can be sliced\n",
"* Since arrays may be multidimensional, you must specify a slice for each dimension of the array\n",
"\n",
"Here is an example matrix of **`shape (3, 4)`** (3 rows and 4 columns) and **`rank 2`** : \n",
"\n",
"\n",
"1 | \n",
"2 | \n",
"3 | \n",
"4 | \n",
"
\n",
"\n",
"5 | \n",
"6 | \n",
"7 | \n",
"8 | \n",
"
\n",
"\n",
"9 | \n",
"10 | \n",
"11 | \n",
"12 | \n",
"
\n",
"
"
]
},
{
"cell_type": "code",
"metadata": {
"id": "rAev-j_hXQ7Z",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "4707c07d-d442-4299-e827-7d04a964294a"
},
"source": [
"import numpy as np\n",
"\n",
"a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
"\n",
"# Use slicing to pull out the subarray consisting of the first 2 rows and columns 1 and 2\n",
"b = a[:2, 1:3]\n",
"\n",
"print( b )"
],
"execution_count": 98,
"outputs": [
{
"output_type": "stream",
"text": [
"[[2 3]\n",
" [6 7]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "IURLlGFuXQ7b",
"colab_type": "text"
},
"source": [
"A **slice of an array is a view into the same data**, so modifying it will modify the original array. \n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hLHXDVIfP-DV",
"colab_type": "text"
},
"source": [
"\n",
"\n",
"1 | \n",
"2 | \n",
"3 | \n",
"4 | \n",
"
\n",
"\n",
"5 | \n",
"6 | \n",
"7 | \n",
"8 | \n",
"
\n",
"\n",
"9 | \n",
"10 | \n",
"11 | \n",
"12 | \n",
"
\n",
"
"
]
},
{
"cell_type": "code",
"metadata": {
"id": "dPlK4fd8XQ7b",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "e9bc7bad-504c-4ef7-f97d-7bb5b3f11952"
},
"source": [
"b[0, 0] = 77 # b[0, 0] is the same piece of data as a[0, 1]\n",
"print( a)"
],
"execution_count": 99,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 1 77 3 4]\n",
" [ 5 6 7 8]\n",
" [ 9 10 11 12]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "x1MeDuPNQoj1",
"colab_type": "text"
},
"source": [
"**Then, how can we make a copy (not reference) of an array?**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "IVRUvUKGQwMW",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 121
},
"outputId": "b08c392e-47d3-45ac-aaef-b8ca7aa83305"
},
"source": [
"c = np.copy(a)\n",
"c[0, 0] = 100\n",
"print(c)\n",
"print(a)"
],
"execution_count": 100,
"outputs": [
{
"output_type": "stream",
"text": [
"[[100 77 3 4]\n",
" [ 5 6 7 8]\n",
" [ 9 10 11 12]]\n",
"[[ 1 77 3 4]\n",
" [ 5 6 7 8]\n",
" [ 9 10 11 12]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qWMdmRkHXQ7f",
"colab_type": "text"
},
"source": [
"You can also **mix integer indexing with slice indexing**. However, doing so will yield an array of lower rank than the original array."
]
},
{
"cell_type": "code",
"metadata": {
"id": "c3cuzy1TXQ7g",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "966c5d74-4b94-43ed-ab33-274a62cf4a1b"
},
"source": [
"# Create the following rank 2 array with shape (3, 4)\n",
"a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
"print(a)"
],
"execution_count": 101,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 1 2 3 4]\n",
" [ 5 6 7 8]\n",
" [ 9 10 11 12]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FvuHBRJ6XQ7h",
"colab_type": "text"
},
"source": [
"Two ways of accessing the data in the middle row of the array:\n",
"1. Mixing integer indexing with slices yields an array of lower rank.\n",
"2. Using only slices yields an array of the same rank as the original array.\n",
"\n",
"\n",
"\n",
"1 | \n",
"2 | \n",
"3 | \n",
"4 | \n",
"
\n",
"\n",
"5 | \n",
"6 | \n",
"7 | \n",
"8 | \n",
"
\n",
"\n",
"9 | \n",
"10 | \n",
"11 | \n",
"12 | \n",
"
\n",
"
"
]
},
{
"cell_type": "code",
"metadata": {
"id": "CApqLqc1XQ7h",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "dc608d93-ec67-4df9-a106-b0d43e14e9e8"
},
"source": [
"row_r1 = a[1, :] # Rank 1 view of the second row of a \n",
"row_r2 = a[1:2, :] # Rank 2 view of the second row of a\n",
"row_r3 = a[[1], :] # Rank 2 view of the second row of a\n",
"print( row_r1, row_r1.shape )\n",
"print( row_r2, row_r2.shape )\n",
"print( row_r3, row_r3.shape )"
],
"execution_count": 102,
"outputs": [
{
"output_type": "stream",
"text": [
"[5 6 7 8] (4,)\n",
"[[5 6 7 8]] (1, 4)\n",
"[[5 6 7 8]] (1, 4)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "R8AQk2UHXQ7k",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "3ca2b0ab-252f-45cb-a7cd-da0bdfdfb18b"
},
"source": [
"# We can make the same distinction when accessing columns of an array:\n",
"col_r1 = a[:, 1]\n",
"col_r2 = a[:, 1:2]\n",
"print( col_r1, col_r1.shape )\n",
"print( col_r2, col_r2.shape )"
],
"execution_count": 103,
"outputs": [
{
"output_type": "stream",
"text": [
"[ 2 6 10] (3,)\n",
"[[ 2]\n",
" [ 6]\n",
" [10]] (3, 1)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wfAhKyA4XQ7m",
"colab_type": "text"
},
"source": [
"**Integer array indexing** \n",
"When you index into numpy arrays using slicing, the resulting array view will always be a subarray of the original array. In contrast, integer array indexing allows you to construct arbitrary arrays using the data from another array. Here is an example:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "xhBzCKMsXQ7m",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "e915f5b2-1ee0-4a9c-9ecf-84e59d278ffa"
},
"source": [
"a = np.array([[1,2], [3, 4], [5, 6]])\n",
"print ('a = ')\n",
"print(a)"
],
"execution_count": 104,
"outputs": [
{
"output_type": "stream",
"text": [
"a = \n",
"[[1 2]\n",
" [3 4]\n",
" [5 6]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "rCfx-k9MCiJP",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "8b1888cd-c183-47ab-8107-66959421ead0"
},
"source": [
"# An example of integer array indexing.\n",
"# The returned array will have shape (2,)\n",
"print (' => ')\n",
"print( a[[0, 1], [0, 1]] )"
],
"execution_count": 105,
"outputs": [
{
"output_type": "stream",
"text": [
" => \n",
"[1 4]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "HE8KYNC2CoKp",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "dec58a15-3fab-4ade-bb24-7db24fdb2fb5"
},
"source": [
"# The returned array will have shape (3,)\n",
"print (' => ')\n",
"print( a[[0, 1, 2], [0, 1, 0]] )"
],
"execution_count": 106,
"outputs": [
{
"output_type": "stream",
"text": [
" => \n",
"[1 4 5]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "z6ZD8F6qCr7i",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "3f737722-7594-4f72-8e6e-eff79ba96a63"
},
"source": [
"# The above example of integer array indexing is equivalent to this:\n",
"print (' => ')\n",
"print( np.array([a[0, 0], a[1, 1], a[2, 0]]) )"
],
"execution_count": 107,
"outputs": [
{
"output_type": "stream",
"text": [
" => \n",
"[1 4 5]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "RG_LOvLsXQ7n",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "86bad880-9e97-4c18-c15d-c5b9cc335bff"
},
"source": [
"# When using integer array indexing, you can reuse the same\n",
"# element from the source array:\n",
"print(a[[0, 0], [1, 1]])\n",
"\n",
"# Equivalent to the previous integer array indexing example\n",
"print(np.array([a[0, 1], a[0, 1]]))"
],
"execution_count": 108,
"outputs": [
{
"output_type": "stream",
"text": [
"[2 2]\n",
"[2 2]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WxkHAebYXQ7p",
"colab_type": "text"
},
"source": [
"One useful trick with integer array indexing is **selecting** or mutating **one element from each row of a matrix**:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "YpRfec-JXQ7p",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "7c450a95-b21e-4f8f-ffa4-3cdebc5413ad"
},
"source": [
"# Create a new array from which we will select elements\n",
"a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"print(a)"
],
"execution_count": 109,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 1 2 3]\n",
" [ 4 5 6]\n",
" [ 7 8 9]\n",
" [10 11 12]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "-b81zUgwXQ7q",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "7a5f96b0-ba9f-48a9-e659-c537b4797256"
},
"source": [
"# Create an array of indices\n",
"b = np.array([0, 2, 0, 1])\n",
"print(b)"
],
"execution_count": 110,
"outputs": [
{
"output_type": "stream",
"text": [
"[0 2 0 1]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "KknlUec9UWA3",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "a1076a7e-94b9-417d-f4ed-cd39dc3042ad"
},
"source": [
"print(np.arange(4))\n",
"# Select one element from each row of a using the indices in b\n",
"print( a[np.arange(4), b] ) # Prints \"[ 1 6 7 11]\""
],
"execution_count": 111,
"outputs": [
{
"output_type": "stream",
"text": [
"[0 1 2 3]\n",
"[ 1 6 7 11]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "a3UVzr5RY0wZ",
"colab_type": "text"
},
"source": [
""
]
},
{
"cell_type": "code",
"metadata": {
"id": "-qXbsJCpXQ7s",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "75790cd4-6159-46d0-e58b-b98be99b95e1"
},
"source": [
"# Mutate one element from each row of a using the indices in b\n",
"a[np.arange(4), b] += 10\n",
"print(a)"
],
"execution_count": 112,
"outputs": [
{
"output_type": "stream",
"text": [
"[[11 2 3]\n",
" [ 4 5 16]\n",
" [17 8 9]\n",
" [10 21 12]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "w3JAoyaMXQ7s",
"colab_type": "text"
},
"source": [
"**Boolean array indexing** \n",
"Boolean array indexing lets you pick out arbitrary elements of an array. Frequently this type of indexing is used to select the elements of an array that satisfy some condition. Here is an example:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "sfXO99trXQ7t",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "4ea99f40-92eb-4f9c-95da-932fdd839cc8"
},
"source": [
"a = np.array([[1,2], [3, 4], [5, 6]])\n",
"print(a)"
],
"execution_count": 113,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1 2]\n",
" [3 4]\n",
" [5 6]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "fX_dlTjn8lqs",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "c48c09a7-342f-4143-cac1-cfabf930c7b7"
},
"source": [
"bool_idx = (a > 2) # Find the elements of a that are bigger than 2;\n",
" # this returns a numpy array of Booleans of the same\n",
" # shape as a, where each slot of bool_idx tells\n",
" # whether that element of a is > 2.\n",
"print(bool_idx)"
],
"execution_count": 114,
"outputs": [
{
"output_type": "stream",
"text": [
"[[False False]\n",
" [ True True]\n",
" [ True True]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "ZzoMvo5cXQ7t",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "f975a7ea-98b0-42f3-cea3-f6776d173356"
},
"source": [
"# We use boolean array indexing to construct a \"rank 1 array\"\n",
"# consisting of the elements of a corresponding to the True values\n",
"# of bool_idx\n",
"print(a[bool_idx])"
],
"execution_count": 115,
"outputs": [
{
"output_type": "stream",
"text": [
"[3 4 5 6]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "oMzKQjvr8fsI",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "af26d9fc-5d95-46f2-a044-48a90a021c4e"
},
"source": [
"# We can do all of the above in a single concise statement:\n",
"print(a[a > 2])"
],
"execution_count": 116,
"outputs": [
{
"output_type": "stream",
"text": [
"[3 4 5 6]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "pSpdCr-0XQ7w",
"colab_type": "text"
},
"source": [
"##➛Datatypes"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YOlRJE6BXQ7w",
"colab_type": "text"
},
"source": [
"* Every numpy array is a grid of elements **of the same type** (unlike a Python list)\n",
"* Numpy provides a large set of numeric datatypes that you can use to construct arrays\n",
"* Numpy tries to guess a datatype when you create an array, but functions that construct arrays usually also include an optional argument to explicitly specify the datatype\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "oQrbxjqBXQ7w",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "d4c13c34-33ad-476b-ee98-5b219ed5a90a"
},
"source": [
"x = np.array([1, 2]) # Let numpy choose the datatype\n",
"y = np.array([1.0, 2.0]) # Let numpy choose the datatype\n",
"z = np.array([1, 2], dtype = np.int32) # Force a particular datatype\n",
"\n",
"print( x.dtype, y.dtype, z.dtype )"
],
"execution_count": 117,
"outputs": [
{
"output_type": "stream",
"text": [
"int64 float64 int32\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wgEzeLhVXQ7x",
"colab_type": "text"
},
"source": [
"Datatypes [documentation](http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "N16naI-NXQ7x",
"colab_type": "text"
},
"source": [
"##➛Array math"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7n1dwJK7XQ7x",
"colab_type": "text"
},
"source": [
"* Basic mathematical functions operate elementwise on arrays\n",
"* These are available as both (a) operator overloads, and (b) functions in the numpy module"
]
},
{
"cell_type": "code",
"metadata": {
"id": "qficzQ9nXQ7y",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "a8edbcbd-ccdd-4d5b-9093-1d083fcc6e72"
},
"source": [
"x = np.array([[1,2],[3,4]], dtype = np.float64)\n",
"y = np.array([[5,6],[7,8]], dtype = np.float64)\n",
"\n",
"# Elementwise sum; both produce the array\n",
"print(x + y) # operator overload\n",
"print(np.add(x, y)) # add available as function"
],
"execution_count": 118,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 6. 8.]\n",
" [10. 12.]]\n",
"[[ 6. 8.]\n",
" [10. 12.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "bFhZI_fpXQ7z",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "8d73269d-3964-4375-bd01-50d24635d536"
},
"source": [
"# Elementwise difference; both produce the array\n",
"print(x - y)\n",
"print(np.subtract(x, y))"
],
"execution_count": 119,
"outputs": [
{
"output_type": "stream",
"text": [
"[[-4. -4.]\n",
" [-4. -4.]]\n",
"[[-4. -4.]\n",
" [-4. -4.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "T7guDPz2XQ71",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "e98ecb1a-0318-4db6-d00c-db1c0779ab1e"
},
"source": [
"# Elementwise product; both produce the array\n",
"print(x * y)\n",
"print(np.multiply(x, y))"
],
"execution_count": 120,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 5. 12.]\n",
" [21. 32.]]\n",
"[[ 5. 12.]\n",
" [21. 32.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "G6vp6WaJXQ72",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "87df373a-a898-4ecd-cbc3-a1e6045f399e"
},
"source": [
"# Elementwise division; both produce the array\n",
"print(x / y)\n",
"print(np.divide(x, y))"
],
"execution_count": 121,
"outputs": [
{
"output_type": "stream",
"text": [
"[[0.2 0.33333333]\n",
" [0.42857143 0.5 ]]\n",
"[[0.2 0.33333333]\n",
" [0.42857143 0.5 ]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "WVDEHLDvXQ74",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "02c72298-a2e8-4713-b39d-48749f1c2884"
},
"source": [
"# Elementwise square root; produces the array\n",
"print(np.sqrt(x))"
],
"execution_count": 122,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1. 1.41421356]\n",
" [1.73205081 2. ]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ptMVErNGXQ75",
"colab_type": "text"
},
"source": [
"Elementwise Multiplication vs Dot Product:\n",
"* `*` is elementwise multiplication, **not matrix multiplication**\n",
"* Use the `dot` function to compute inner products of vectors, to multiply a vector by a matrix, and to multiply matrices\n",
"* `dot` is available both as a function in the numpy module and as an instance method of array objects"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "m3HIt9jFhyNk",
"colab_type": "text"
},
"source": [
"**Dot Product** \n",
"* `.dot()` function returns the dot product of two arrays\n",
"* For 1-D arrays, it is the inner product of the vectors\n",
"* For 2-D vectors, it is the equivalent to matrix multiplication\n",
"* If the dimensions don't match for matrix multiplication, it performs matrix/vector multiplication\n",
"* For N-dimensional arrays, it is a sum product over the last axis of a and the second-last axis of b\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JgytcMZv4C5h",
"colab_type": "text"
},
"source": [
"**Examples:**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "e6jeDGEpXQ76",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "9619ec81-8e90-42a0-9175-f5c40e1f3c62"
},
"source": [
"v = np.array([9,10])\n",
"w = np.array([11, 12])\n",
"# Inner product of vectors\n",
"print(v.dot(w))\n",
"print(np.dot(v, w))"
],
"execution_count": 123,
"outputs": [
{
"output_type": "stream",
"text": [
"219\n",
"219\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "OleS9R2XXQ78",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "8ccaf135-2295-4bc0-e6d0-58a4878c9578"
},
"source": [
"x = np.array([[1,2],[3,4]])\n",
"# Matrix / vector product; both produce the rank 1 array\n",
"print(x.dot(v))\n",
"print(np.dot(x, v))"
],
"execution_count": 124,
"outputs": [
{
"output_type": "stream",
"text": [
"[29 67]\n",
"[29 67]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "W6E5lkHVXQ7-",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "40e8f89e-0ef4-4396-e2e2-7dcfcbb385aa"
},
"source": [
"y = np.array([[5,6],[7,8]])\n",
"# Matrix / matrix product; both produce the rank 2 array\n",
"print(x * y)\n",
"print(np.dot(x, y))"
],
"execution_count": 125,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 5 12]\n",
" [21 32]]\n",
"[[19 22]\n",
" [43 50]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6vmKfrImXQ8A",
"colab_type": "text"
},
"source": [
"Numpy provides many useful functions for performing computations on arrays; one of the most useful is `sum`:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "XSTvjf3YXQ8A",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 173
},
"outputId": "64f6ef10-2af8-4c31-dbe5-3b0418b7264d"
},
"source": [
"import numpy as np\n",
"x = np.array([[1,2],[3,4]])\n",
"print('x =')\n",
"print(x)\n",
"print('sum =')\n",
"print(np.sum(x)) # Compute sum of all elements\n",
"print('sum along axis 0 =')\n",
"print(np.sum(x, axis=0)) # Compute sum of each column\n",
"print('sum along axis 1 =')\n",
"print(np.sum(x, axis=1)) # Compute sum of each row"
],
"execution_count": 126,
"outputs": [
{
"output_type": "stream",
"text": [
"x =\n",
"[[1 2]\n",
" [3 4]]\n",
"sum =\n",
"10\n",
"sum along axis 0 =\n",
"[4 6]\n",
"sum along axis 1 =\n",
"[3 7]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "olOcsERol2lN",
"colab_type": "text"
},
"source": [
"To transpose a matrix, simply use the T attribute of an array object:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "d-jS9i5iXQ8C",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "de5af5a0-8f6f-45a7-9f7c-f15fab3ab138"
},
"source": [
"print(x)\n",
"print(x.T)"
],
"execution_count": 127,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1 2]\n",
" [3 4]]\n",
"[[1 3]\n",
" [2 4]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vLvszOw_l_nS",
"colab_type": "text"
},
"source": [
"Numpy arrays can also be reshaped using `.reshape()`"
]
},
{
"cell_type": "code",
"metadata": {
"id": "b69dRW1bl-N1",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "2c09b606-fa81-4f68-cf29-572530061c95"
},
"source": [
"x = np.array([[1,2],[3,4]])\n",
"print(x.shape)\n",
"\n",
"y = np.reshape(x, (1, 4))\n",
"print(y.shape)\n",
"print(y)"
],
"execution_count": 128,
"outputs": [
{
"output_type": "stream",
"text": [
"(2, 2)\n",
"(1, 4)\n",
"[[1 2 3 4]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8pF1yyhiXQ8B",
"colab_type": "text"
},
"source": [
"Mathematical functions [documentation](http://docs.scipy.org/doc/numpy/reference/routines.math.html)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6Y70yMgAXQ8E",
"colab_type": "text"
},
"source": [
"##➛Introduction to Broadcasting (intuition)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kZakfoZeXQ8F",
"colab_type": "text"
},
"source": [
"* Broadcasting is a powerful mechanism that **allows numpy to work with arrays of different shapes when performing arithmetic operations**\n",
"* Frequently we have **a smaller array and a larger array**, and we want to **use the smaller array multiple times to perform some operation on the larger array**\n",
"\n",
"Suppose that we want to add a constant vector to each row of a matrix:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "0C6PHInsXQ8F",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 104
},
"outputId": "874036de-d930-4cf7-b7d3-5d7fa6ba9275"
},
"source": [
"# We will add the vector v to each row of the matrix x,\n",
"# storing the result in the matrix y\n",
"x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"v = np.array([1, 0, 1])\n",
"y = np.empty_like(x) # Create an empty matrix with the same shape as x\n",
"print('x: ', x)\n",
"print('v: ', v)"
],
"execution_count": 129,
"outputs": [
{
"output_type": "stream",
"text": [
"x: [[ 1 2 3]\n",
" [ 4 5 6]\n",
" [ 7 8 9]\n",
" [10 11 12]]\n",
"v: [1 0 1]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8HssZd8mnh0p",
"colab_type": "text"
},
"source": [
"We would like to add `v` to `x`. Here is a naive way of doing so (**Method 1**):"
]
},
{
"cell_type": "code",
"metadata": {
"id": "4Z_KEwltnC7g",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "4ece7a15-ebb8-4b77-9042-36156c145045"
},
"source": [
"# Add the vector v to each row of the matrix x with an explicit loop\n",
"for i in range(4):\n",
" x[i, :] = x[i, :] + v\n",
"print(x)"
],
"execution_count": 130,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 2 2 4]\n",
" [ 5 5 7]\n",
" [ 8 8 10]\n",
" [11 11 13]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5-I9Nf-sXQ8G",
"colab_type": "text"
},
"source": [
"**This works**; however when the matrix `x` is very large, computing an explicit loop in Python **could be slow**."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "U53xdShpoVSH",
"colab_type": "text"
},
"source": [
"Note that adding the vector v to each row of the matrix `x` is equivalent to forming a matrix `vv` by stacking multiple copies of `v` vertically, then performing elementwise summation of `x` and `vv`. We could implement this approach like this (**Method 2**):"
]
},
{
"cell_type": "code",
"metadata": {
"id": "vCRexPyNXQ8G",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "8c52309b-ad51-4873-8606-c58ffaf0b08f"
},
"source": [
"vv = np.tile(v, (4, 1)) # Stack 4 copies of v on top of each other\n",
"print(vv) "
],
"execution_count": 131,
"outputs": [
{
"output_type": "stream",
"text": [
"[[1 0 1]\n",
" [1 0 1]\n",
" [1 0 1]\n",
" [1 0 1]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "nnWsd_9uXQ8I",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 87
},
"outputId": "009fbde3-04ef-40a1-a1bd-83ad4d4700b1"
},
"source": [
"y = x + vv # Add x and vv elementwise\n",
"print(y)"
],
"execution_count": 132,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 3 2 5]\n",
" [ 6 5 8]\n",
" [ 9 8 11]\n",
" [12 11 14]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cckaw_HxXQ8K",
"colab_type": "text"
},
"source": [
"Numpy broadcasting allows us to perform this computation **without actually creating multiple copies of v**. Consider this version, **using broadcasting** (**Method 3**):"
]
},
{
"cell_type": "code",
"metadata": {
"id": "MUP7ja6RXQ8K",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 208
},
"outputId": "ac1c7f4f-5f27-4c9a-f89a-521a6b87d3f4"
},
"source": [
"import numpy as np\n",
"\n",
"# We will add the vector v to each row of the matrix x,\n",
"x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])\n",
"v = np.array([1, 0, 1])\n",
"y = x + v # Add v to each row of x using broadcasting\n",
"\n",
"print(x)\n",
"print('')\n",
"print(v)\n",
"print('')\n",
"print(y)"
],
"execution_count": 133,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 1 2 3]\n",
" [ 4 5 6]\n",
" [ 7 8 9]\n",
" [10 11 12]]\n",
"\n",
"[1 0 1]\n",
"\n",
"[[ 2 2 4]\n",
" [ 5 5 7]\n",
" [ 8 8 10]\n",
" [11 11 13]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vnsTScwIXQ8M",
"colab_type": "text"
},
"source": [
"##➛Broadcasting \n",
"* The term \"broadcasting\" describes how numpy treats arrays with different shapes during arithmetic operations\n",
"* The smaller array is \"broadcast\" across the larger array so that they have compatible shapes\n",
"\n",
"The simplest broadcasting example occurs when an array and a scalar value are combined in an operation:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "NxnpBm9wjvFR",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "b157daf7-2a7d-4e01-cd62-ac7d9339d127"
},
"source": [
"import numpy as np\n",
"a = np.array([1.0, 2.0, 3.0])\n",
"b = 2.0\n",
"print(a * b)"
],
"execution_count": 134,
"outputs": [
{
"output_type": "stream",
"text": [
"[2. 4. 6.]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6HY5XCzZkEqJ",
"colab_type": "text"
},
"source": [
"**Explanation:**\n",
"* We can think of the **scalar b being stretched during the arithmetic operation** into an array with the same shape as a\n",
"* The new elements in b are simply copies of the original scalar\n",
"* The **stretching analogy is only conceptual**. NumPy is smart enough to use the original scalar value **without actually making copies**, so that broadcasting operations are **as memory and computationally efficient** as possible."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kn8J2clskoNA",
"colab_type": "text"
},
"source": [
"##➛Broadcasting Rules\n",
"\n",
"When operating on two arrays, NumPy **compares their shapes element-wise**. It starts with the trailing dimensions, and works its way forward. Two dimensions are compatible for broadcasting when\n",
"\n",
"1. they are equal, or\n",
"1. one of them is 1\n",
"\n",
"If these conditions are not met, a `ValueError: operands could not be broadcast together` exception is thrown, indicating that the arrays have incompatible shapes. The **size of the resulting array is the maximum size along each dimension of the input arrays**.\n",
"\n",
"Arrays do not need to have the same number of dimensions. For example, if you have a 256x256x3 array of RGB values, and you want to scale each color in the image by a different value, you can multiply the image by a one-dimensional array with 3 values. Lining up the sizes of the trailing axes of these arrays according to the broadcast rules, shows that they are compatible:\n",
"```\n",
"Image (3d array): 256 x 256 x 3\n",
"Scale (1d array): 3 \n",
"Result (3d array): 256 x 256 x 3\n",
"```\n",
"\n",
"\n",
"When either of the dimensions compared is one, the other is used. In other words, dimensions with size 1 are stretched or “copied” to match the other. Here, the scaling vector can be thought of having the dimensions `1 x 1 x 3`."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "z999K1wEpjyL",
"colab_type": "text"
},
"source": [
"##➛Broadcasting Examples\n",
"\n",
"Examples where broadcasting works:\n",
"\n",
"```\n",
"A (4d array): 8 x 1 x 6 x 1\n",
"B (3d array): 7 x 1 x 5\n",
"Result (4d array): 8 x 7 x 6 x 5\n",
"```\n",
"\n",
"```\n",
"A (2d array): 5 x 4\n",
"B (1d array): 1\n",
"Result (2d array): 5 x 4\n",
"```\n",
"\n",
"```\n",
"A (2d array): 5 x 4\n",
"B (1d array): 4\n",
"Result (2d array): 5 x 4\n",
"```\n",
"\n",
"```\n",
"A (3d array): 15 x 3 x 5\n",
"B (3d array): 15 x 1 x 5\n",
"Result (3d array): 15 x 3 x 5\n",
"```\n",
"\n",
"```\n",
"A (3d array): 15 x 3 x 5\n",
"B (2d array): 3 x 5\n",
"Result (3d array): 15 x 3 x 5\n",
"```\n",
"\n",
"```\n",
"A (3d array): 15 x 3 x 5\n",
"B (2d array): 3 x 1\n",
"Result (3d array): 15 x 3 x 5\n",
"```\n",
"\n",
"Examples of shapes that do not broadcast:\n",
"```\n",
"A (1d array): 3\n",
"B (1d array): 4 # trailing dimensions do not match\n",
"```\n",
"```\n",
"A (2d array): 2 x 1\n",
"B (3d array): 8 x 4 x 3 # second from last dimensions mismatched\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "TTdi93LpqfkQ",
"colab_type": "text"
},
"source": [
"**Practice Example 1:**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "NtbSUK-oqRSU",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "0f8b46e0-797f-4be1-80cd-ba51215732ed"
},
"source": [
"x = np.arange(4)\n",
"y = np.ones(5)\n",
"print(x, x.shape)\n",
"print(y, y.shape)"
],
"execution_count": 135,
"outputs": [
{
"output_type": "stream",
"text": [
"[0 1 2 3] (4,)\n",
"[1. 1. 1. 1. 1.] (5,)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "6n10YHyCrUCU",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 167
},
"outputId": "99c40b72-1095-45ec-ab21-e5269fccce9e"
},
"source": [
"# What will be the output?\n",
"print((x + y).shape)"
],
"execution_count": 136,
"outputs": [
{
"output_type": "error",
"ename": "ValueError",
"evalue": "ignored",
"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[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (4,) (5,) "
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "F7io4Bwarino",
"colab_type": "text"
},
"source": [
"**Practice Example 2:**"
]
},
{
"cell_type": "code",
"metadata": {
"id": "8ZZFz5uqrvJ2",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 104
},
"outputId": "8eeaf161-2d94-4cbc-b0c2-21e6f92ad82a"
},
"source": [
"xx = x.reshape(4,1)\n",
"print(xx, xx.shape)\n",
"print(y, y.shape)"
],
"execution_count": 137,
"outputs": [
{
"output_type": "stream",
"text": [
"[[0]\n",
" [1]\n",
" [2]\n",
" [3]] (4, 1)\n",
"[1. 1. 1. 1. 1.] (5,)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "x-LqF-2mr3o3",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 35
},
"outputId": "b8b64377-92ce-4451-8cf3-13f4456430cc"
},
"source": [
"# What will be the output?\n",
"print((xx + y).shape)"
],
"execution_count": 138,
"outputs": [
{
"output_type": "stream",
"text": [
"(4, 5)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "szrxcNXYsX9I",
"colab_type": "text"
},
"source": [
"##➛Outer Product using Broadcasting"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "34d7mdavjvb7",
"colab_type": "text"
},
"source": [
"Broadcasting provides a convenient way of taking the outer product (or any other outer operation) of two arrays. The following **example shows an outer product operation** of two 1-d arrays:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "GfOKBe-QXQ8N",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
},
"outputId": "3060b6bf-7da4-4b87-a0a7-9aaf6047b8cc"
},
"source": [
"import numpy as np\n",
"\n",
"a = np.array([0.0, 10.0, 20.0, 30.0])\n",
"b = np.array([1.0, 2.0, 3.0])\n",
"\n",
"print(a, a.shape)\n",
"print(b, b.shape)"
],
"execution_count": 139,
"outputs": [
{
"output_type": "stream",
"text": [
"[ 0. 10. 20. 30.] (4,)\n",
"[1. 2. 3.] (3,)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "pEuI7UBiYSAM",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 167
},
"outputId": "8b918e87-9e6a-4b25-db24-1f86b073f7c1"
},
"source": [
"print(a * b)"
],
"execution_count": 140,
"outputs": [
{
"output_type": "error",
"ename": "ValueError",
"evalue": "ignored",
"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[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (4,) (3,) "
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DAerJHzEdRyG",
"colab_type": "text"
},
"source": [
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Y0MZIe29cAll",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 69
},
"outputId": "76fb8e8d-d0ef-4759-afe6-0330fe305bdf"
},
"source": [
"#Here the newaxis index operator inserts a new axis into a, making it a two-dimensional 4x1 array\n",
"print( a * b.reshape(3,1) )"
],
"execution_count": 141,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 0. 10. 20. 30.]\n",
" [ 0. 20. 40. 60.]\n",
" [ 0. 30. 60. 90.]]\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "L1wMP325XQ8U",
"colab_type": "text"
},
"source": [
"Functions that support broadcasting are known as universal functions. Here is the [list](http://docs.scipy.org/doc/numpy/reference/ufuncs.html#available-ufuncs).\n",
"\n",
"Broadcasting [documentation](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html).\n"
]
}
]
}