{ "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8.10" } }, "nbformat": 4, "nbformat_minor": 1, "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "Let's look at how to extract pieces from an array or modify only some of its parts. For this, we\n", "have two tools:\n", " \n", "* the extraction according to the indices\n", "* the extraction by applying a logical filter on the values" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "## Filter by indices\n", "\n", "We can extract values from an array according to its indices as we did for lists. For each dimension of the table, you can indicate\n", "\n", "* the value of the desired index (an integer)\n", "* a list of `start:end:jump` indices. Thus `1:6:2` means the odd values between index 1 and index 6 excluded. The `start`, `end` and `jump` values are optional:\n", " * `:5` gives the first 5 values (indices 0,1,2,3 and 4)\n", " * `3:` gives 4th to last values\n", " * `::3` returns a value every 3 from the beginning to the end of the array.\n", "* an explicit list of indices like `[1,3,-2]` (negative values means start from the end, hence `-2` is the penultimate index)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3]\n", " [ 4 5 6 7]\n", " [ 8 9 10 11]] \n", "\n", "[4 5 6 7] \n", "\n", "[[0 1]\n", " [4 5]] \n", "\n", "[ 3 11] \n", "\n", "[[ 0 3]\n", " [ 4 7]\n", " [ 8 11]]\n" ] } ], "source": [ "a = np.arange(12).reshape(3,4)\n", "print(a, '\\n')\n", "print(a[1, :], '\\n') # 2nd line\n", "print(a[0:2, 0:2], '\\n') # top left sub-matrix\n", "print(a[::2, -1], '\\n') # even lines, last column\n", "print(a[:, [0,-1]]) # first and last column" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "It is thus possible to indicate that an operation only applies to an extract from the table by indicating\n", "which cells of the table will be modified:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 101, 2, 103],\n", " [ 4, 5, 6, 7],\n", " [ 8, 109, 10, 111]])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[::2, 1::2] += 100\n", "a" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "It also makes it possible to simply write calculations such as extracting a grayscale image from a color image:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "image = np.random.randint(256, size=(800, 600, 3)) # RGB 800x600 image\n", "gray_image = 0.2126 * image[:,:,0] + 0.7152 * image[:,:,1] + 0.0722 * image[:,:,2]" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "You can also use `...` to replace multiple indices like `image[...,0] == image[:,:,0]`" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "## Logical filters\n", "\n", "### A filter = a logical condition\n", "\n", "Numpy allows you to simply extract the values ​​that meet a logical condition.\n", "\n", "To do this, we use a filter, namely a Boolean array that is placed on an array of the same size, imagining that the True boxes are windows and False are walls. The result is the set of values ​​seen through the windows ordered by their index.\n", "\n", "The result is always a 1-dimensional array unless you use `where`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The filter a > 5 is\n", " [[False False False False]\n", " [False False True True]\n", " [ True True True True]]\n" ] }, { "data": { "text/plain": [ "array([ 6, 7, 8, 9, 10, 11])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(12).reshape(3,4)\n", "fil = a > 5 # a > 5 means all VALUES greater than 5\n", "print(\"The filter a > 5 is\\n\", fil)\n", "a[fil] # apply the filter and show the result (1D array)" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "It is easier and more readable to write the logical condition where we normally put the indices, namely between the square brackets:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 6, 7, 8, 9, 10, 11])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[a>5]" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "#### When the goal is the filter\n", "\n", "The filter can be used for something other than selecting values ​​from our array. It can be the result on which we want to work, for example for a population `fil = (age == weight)`. It is an array of Boolean which gives true cases and other false cases i.e. 0s and 1s.\n", "\n", "Thus, with a `fil` filter, we can know\n", "\n", "| | | |\n", "|:-|:-|:-|\n", "| how many cases are true: |`fil.sum()` | |\n", "| if there is at least one true case: |`fil.sum() > 0` | Numpy also offers `np.any(fil)` |\n", "| if all cases are true: |`fil.prod() == 1` | Numpy also offers `np.all(fil)` |\n", "| if at least one case is false: |`fil.prod() == 0` |\n", "|if all cases are false:| `fil.sum() == 0` |" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "### `where` to handle non-filter values\n", "\n", "To preserve the shape of the array, it is necessary to tell it what to do with the values that do not meet the condition. To do this, we use the [`where`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html) function:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 0, 0, 0],\n", " [ 0, 0, 6, 7],\n", " [ 8, 9, 10, 11]])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.where(a > 5, a, 0) # if a > 5 then a else 0" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "We can make all imaginable filters that give a boolean array." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0, -1, -1, 6],\n", " [-1, -1, 12, -1],\n", " [-1, 18, -1, -1]])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.where(a%3 == 0, 2*a, -1) # if a modulo 3 is 0 then 2 times a else -1" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "### Update a table with a filter\n", "\n", "Another way to maintain the shape of the array is to change only the values ​​that match the filter." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3],\n", " [ 4, 5, 200, 200],\n", " [200, 200, 200, 200]])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(12).reshape(3,4)\n", "a[a > 5] = 200\n", "a" ] }, { "cell_type": "markdown", "metadata": { "lang": "en" }, "source": [ "Here's how to add 100 to all values ​​in the array that are perfect squares as well as to the value 5:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[100, 101, 2, 3],\n", " [104, 105, 6, 7],\n", " [ 8, 109, 10, 11]])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(12).reshape(3,4)\n", "a[(np.round(np.sqrt(a)) - np.sqrt(a) == 0) | (a==5)] += 100 # | is OR (AND is &)\n", "a" ] }, { "cell_type": "markdown", "metadata": { "variables": { " PreviousNext(\"np01 Numpy Introduction.ipynb\", \"np03 Manipulations.ipynb\")": "                                                                                                                                                                                                                                                                                                                                                                                                               
np01 Numpy Introduction  ← →  np03 Manipulations

 " } }, "source": [ "{{ PreviousNext(\"np01 Numpy Introduction.ipynb\", \"np03 Manipulations.ipynb\")}}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ] }