{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Numpy (tableaux de données multi-dimensionnels) \n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Librairie de calcul numérique permettant notamment de manipuler des tableaux de dimension quelconque." ] }, { "cell_type": "code", "execution_count": 203, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 204, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
run previous cell, wait for 2 seconds
\n", "" ], "text/plain": [ "" ] }, "execution_count": 204, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from jyquickhelper import add_notebook_menu\n", "add_notebook_menu()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Introduction\n", "\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* `numpy` est un module utilisé dans presque tous les projets de calcul numérique sous Python\n", " * Il fournit des structures de données performantes pour la manipulation de vecteurs, matrices et tenseurs plus généraux\n", " * `numpy` est écrit en C et en Fortran d'où ses performances élevées lorsque les calculs sont vectorisés (formulés comme des opérations sur des vecteurs/matrices)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour utiliser `numpy` il faut commencer par l'importer :" ] }, { "cell_type": "code", "execution_count": 205, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "Dans la terminologie `numpy`, vecteurs, matrices et autres tenseurs sont appelés *arrays*.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Création d'*arrays* `numpy` \n", "\n", "Plusieurs possibilités:\n", "\n", " * à partir de listes ou n-uplets Python\n", " * en utilisant des fonctions dédiées, telles que `arange`, `linspace`, etc.\n", " * par chargement à partir de fichiers\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "#### À partir de listes\n", "\n", "Au moyen de la fonction `numpy.array` :" ] }, { "cell_type": "code", "execution_count": 206, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 3 2 4]\n", "\n" ] } ], "source": [ "# un vecteur : l'argument de la fonction est une liste Python\n", "v = np.array([1, 3, 2, 4])\n", "print(v)\n", "print(type(v))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour définir une matrice (array de dimension 2 pour numpy):\n" ] }, { "cell_type": "code", "execution_count": 207, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2]\n", " [3 4]]\n" ] } ], "source": [ "# une matrice : l'argument est une liste de liste\n", "M = np.array([[1, 2], [3, 4]])\n", "print(M)" ] }, { "cell_type": "code", "execution_count": 208, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 208, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M[0, 0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les objets `v` et `M` sont tous deux du type `ndarray` (fourni par `numpy`)" ] }, { "cell_type": "code", "execution_count": 209, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(numpy.ndarray, numpy.ndarray)" ] }, "execution_count": 209, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(v), type(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`v` et `M` ne diffèrent que par leur taille, que l'on peut obtenir via la propriété `shape` :" ] }, { "cell_type": "code", "execution_count": 210, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(4,)" ] }, "execution_count": 210, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.shape" ] }, { "cell_type": "code", "execution_count": 211, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(2, 2)" ] }, "execution_count": 211, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour obtenir le nombre d'éléments d'un *array* :" ] }, { "cell_type": "code", "execution_count": 212, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 212, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.size" ] }, { "cell_type": "code", "execution_count": 213, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 213, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.size" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut aussi utiliser `numpy.shape` et `numpy.size`" ] }, { "cell_type": "code", "execution_count": 214, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(2, 2)" ] }, "execution_count": 214, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les *arrays* ont un type qu'on obtient via `dtype` :" ] }, { "cell_type": "code", "execution_count": 215, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2]\n", " [3 4]]\n", "int64\n" ] } ], "source": [ "print( M)\n", "print(M.dtype)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les types doivent être respectés lors d'assignations à des *arrays*" ] }, { "cell_type": "code", "execution_count": 216, "metadata": { "collapsed": false }, "outputs": [ { "ename": "ValueError", "evalue": "invalid literal for int() with base 10: 'hello'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/2b/cj2pm60x61s5qlxpmr7g7km00000gn/T/ipykernel_6947/3388738246.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\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\"hello\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'hello'" ] } ], "source": [ "M[0,0] = \"hello\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut modifier le type d'un array après sa déclaration en utilisant *astype*" ] }, { "cell_type": "code", "execution_count": 217, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.5 1. 1. ]\n" ] } ], "source": [ "a = np.array([1,2,3], dtype=np.int64)\n", "b = np.array([2,2,3], dtype=np.int64)\n", "b = b.astype(float)\n", "print(a / b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut définir le type de manière explicite en utilisant le mot clé `dtype` en argument: " ] }, { "cell_type": "code", "execution_count": 218, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1.+0.j, 2.+0.j],\n", " [3.+0.j, 4.+0.j]])" ] }, "execution_count": 218, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M = np.array([[1, 2], [3, 4]], dtype=complex)\n", "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Autres types possibles avec `dtype` : `int`, `float`, `complex`, `bool`, `object`, etc.\n", "\n", " * On peut aussi spécifier la précision en bits: `int64`, `int16`, `float128`, `complex128`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### En utilisant des fonctions de génération d'*arrays*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### arange" ] }, { "cell_type": "code", "execution_count": 219, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 2, 4, 6, 8])" ] }, "execution_count": 219, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# create a range\n", "x = np.arange(0, 10, 2) # arguments: start, stop, step\n", "x" ] }, { "cell_type": "code", "execution_count": 220, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([-1.00000000e+00, -9.00000000e-01, -8.00000000e-01, -7.00000000e-01,\n", " -6.00000000e-01, -5.00000000e-01, -4.00000000e-01, -3.00000000e-01,\n", " -2.00000000e-01, -1.00000000e-01, -2.22044605e-16, 1.00000000e-01,\n", " 2.00000000e-01, 3.00000000e-01, 4.00000000e-01, 5.00000000e-01,\n", " 6.00000000e-01, 7.00000000e-01, 8.00000000e-01, 9.00000000e-01])" ] }, "execution_count": 220, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.arange(-1, 1, 0.1)\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### linspace and logspace" ] }, { "cell_type": "code", "execution_count": 221, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0. , 0.41666667, 0.83333333, 1.25 , 1.66666667,\n", " 2.08333333, 2.5 , 2.91666667, 3.33333333, 3.75 ,\n", " 4.16666667, 4.58333333, 5. , 5.41666667, 5.83333333,\n", " 6.25 , 6.66666667, 7.08333333, 7.5 , 7.91666667,\n", " 8.33333333, 8.75 , 9.16666667, 9.58333333, 10. ])" ] }, "execution_count": 221, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# avec linspace, le début et la fin SONT inclus\n", "np.linspace(0, 10, 25)" ] }, { "cell_type": "code", "execution_count": 222, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])" ] }, "execution_count": 222, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linspace(0, 10, 11)" ] }, { "cell_type": "code", "execution_count": 223, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.00000000e+00 3.03773178e+00 9.22781435e+00 2.80316249e+01\n", " 8.51525577e+01 2.58670631e+02 7.85771994e+02 2.38696456e+03\n", " 7.25095809e+03 2.20264658e+04]\n" ] } ], "source": [ "print(np.logspace(0, 10, 10, base=np.e))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### mgrid" ] }, { "cell_type": "code", "execution_count": 224, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x, y = np.mgrid[0:5, 0:5] " ] }, { "cell_type": "code", "execution_count": 225, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 0, 0, 0, 0],\n", " [1, 1, 1, 1, 1],\n", " [2, 2, 2, 2, 2],\n", " [3, 3, 3, 3, 3],\n", " [4, 4, 4, 4, 4]])" ] }, "execution_count": 225, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x" ] }, { "cell_type": "code", "execution_count": 226, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 2, 3, 4],\n", " [0, 1, 2, 3, 4],\n", " [0, 1, 2, 3, 4],\n", " [0, 1, 2, 3, 4],\n", " [0, 1, 2, 3, 4]])" ] }, "execution_count": 226, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Données aléatoires" ] }, { "cell_type": "code", "execution_count": 227, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from numpy import random" ] }, { "cell_type": "code", "execution_count": 228, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.24864548, 0.63089037, 0.77389506, 0.81783434, 0.79596002],\n", " [0.85558193, 0.22401831, 0.55064774, 0.77261266, 0.17076234],\n", " [0.95389589, 0.90503278, 0.11467454, 0.25471487, 0.74490302],\n", " [0.84278478, 0.0603186 , 0.59791704, 0.11026734, 0.00240362],\n", " [0.81703152, 0.36956662, 0.79248384, 0.67138247, 0.72257048]])" ] }, "execution_count": 228, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# tirage uniforme dans [0,1]\n", "random.rand(5,5) # ou np.random.rand" ] }, { "cell_type": "code", "execution_count": 229, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[-0.45940848, -0.08739989, 1.23701621, -0.99410567, 0.71004674],\n", " [ 0.92328688, -0.42949293, -0.83454461, 0.78319392, 0.42515375],\n", " [-1.76969754, 0.99760808, 0.73659765, -0.04455947, 2.33848227],\n", " [-0.46933546, 1.14501506, -0.80759395, 0.03592718, -0.53140356],\n", " [-0.58504991, -0.05095495, 0.58677105, -0.36585961, -1.49440989]])" ] }, "execution_count": 229, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# tirage suivant une loi normale standard\n", "random.randn(5,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### diag" ] }, { "cell_type": "code", "execution_count": 230, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 0],\n", " [0, 2, 0],\n", " [0, 0, 3]])" ] }, "execution_count": 230, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# une matrice diagonale\n", "np.diag([1,2,3])" ] }, { "cell_type": "code", "execution_count": 231, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 0, 0],\n", " [0, 0, 2, 0],\n", " [0, 0, 0, 3],\n", " [0, 0, 0, 0]])" ] }, "execution_count": 231, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# diagonale avec décalage par rapport à la diagonale principale\n", "np.diag([1,2,3], k=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### zeros, ones et identity" ] }, { "cell_type": "code", "execution_count": 232, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 0, 0])" ] }, "execution_count": 232, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.zeros((3,), dtype=int) # attention zeros(3,3) est FAUX" ] }, { "cell_type": "code", "execution_count": 233, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1., 1., 1.],\n", " [1., 1., 1.],\n", " [1., 1., 1.]])" ] }, "execution_count": 233, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones((3,3))" ] }, { "cell_type": "code", "execution_count": 234, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 0 0]\n", "[[0 0 0]]\n", "[[0]\n", " [0]\n", " [0]]\n" ] } ], "source": [ "print(np.zeros((3,), dtype=int))\n", "print(np.zeros((1, 3), dtype=int))\n", "print(np.zeros((3, 1), dtype=int))" ] }, { "cell_type": "code", "execution_count": 235, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 0. 0.]\n", " [0. 1. 0.]\n", " [0. 0. 1.]]\n" ] } ], "source": [ "print(np.identity(3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### À partir de fichiers d'E/S" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Fichiers séparés par des virgules (CSV)\n", "\n", "Un format fichier classique est le format CSV (comma-separated values), ou bien TSV (tab-separated values). Pour lire de tels fichiers utilisez `numpy.genfromtxt`. Par exemple:" ] }, { "cell_type": "code", "execution_count": 236, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1., 2., 3., 4., 5.],\n", " [ 6., 7., 8., 9., 10.],\n", " [11., 12., 13., 14., 15.],\n", " [16., 17., 18., 19., 20.]])" ] }, "execution_count": 236, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data = np.genfromtxt('files/DONNEES.csv', delimiter=',')\n", "data" ] }, { "cell_type": "code", "execution_count": 237, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(4, 5)" ] }, "execution_count": 237, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A l'aide de `numpy.savetxt` on peut enregistrer un *array* `numpy` dans un fichier txt:" ] }, { "cell_type": "code", "execution_count": 238, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.93055858, 0.78556744, 0.74477941],\n", " [0.86289541, 0.21311052, 0.19970051],\n", " [0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 238, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M = random.rand(3,3)\n", "M" ] }, { "cell_type": "code", "execution_count": 239, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.savetxt(\"random-matrix.txt\", M)" ] }, { "cell_type": "code", "execution_count": 240, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.savetxt(\"random-matrix.csv\", M, fmt='%.5f', delimiter=',') # fmt spécifie le format" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Format de fichier Numpy natif\n", "\n", "Pour sauvegarder et recharger des *array* `numpy` : `numpy.save` et `numpy.load` :" ] }, { "cell_type": "code", "execution_count": 241, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.save(\"random-matrix.npy\", M)" ] }, { "cell_type": "code", "execution_count": 242, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.93055858, 0.78556744, 0.74477941],\n", " [0.86289541, 0.21311052, 0.19970051],\n", " [0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 242, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.load(\"random-matrix.npy\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Autres propriétés des *arrays* `numpy`" ] }, { "cell_type": "code", "execution_count": 243, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.93055858, 0.78556744, 0.74477941],\n", " [0.86289541, 0.21311052, 0.19970051],\n", " [0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 243, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "code", "execution_count": 244, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dtype('float64')" ] }, "execution_count": 244, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.dtype" ] }, { "cell_type": "code", "execution_count": 245, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "8" ] }, "execution_count": 245, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.itemsize # octets par élément" ] }, { "cell_type": "code", "execution_count": 246, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "72" ] }, "execution_count": 246, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.nbytes # nombre d'octets" ] }, { "cell_type": "code", "execution_count": 247, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "8.0" ] }, "execution_count": 247, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.nbytes / M.size" ] }, { "cell_type": "code", "execution_count": 248, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 248, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M.ndim # nombre de dimensions" ] }, { "cell_type": "code", "execution_count": 249, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "2\n" ] } ], "source": [ "print(np.zeros((3,), dtype=int).ndim)\n", "print( np.zeros((1, 3), dtype=int).ndim)\n", "print (np.zeros((3, 1), dtype=int).ndim)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manipulation et Opérations sur les *arrays*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Indexation" ] }, { "cell_type": "code", "execution_count": 250, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 250, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# v est un vecteur, il n'a qu'une seule dimension -> un seul indice\n", "v[0]" ] }, { "cell_type": "code", "execution_count": 251, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.21311051767796552" ] }, "execution_count": 251, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# M est une matrice, ou un array à 2 dimensions -> deux indices \n", "M[1,1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Contenu complet :" ] }, { "cell_type": "code", "execution_count": 252, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.93055858, 0.78556744, 0.74477941],\n", " [0.86289541, 0.21311052, 0.19970051],\n", " [0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 252, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La deuxième ligne :" ] }, { "cell_type": "code", "execution_count": 253, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.86289541, 0.21311052, 0.19970051])" ] }, "execution_count": 253, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut aussi utiliser `:` " ] }, { "cell_type": "code", "execution_count": 254, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.86289541, 0.21311052, 0.19970051])" ] }, "execution_count": 254, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M[1,:] # 2 ème ligne (indice 1)" ] }, { "cell_type": "code", "execution_count": 255, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.78556744, 0.21311052, 0.16492924])" ] }, "execution_count": 255, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M[:,1] # 2 ème colonne (indice 1)" ] }, { "cell_type": "code", "execution_count": 256, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3, 3)\n", "(3,) (3,)\n" ] } ], "source": [ "print(M.shape)\n", "print( M[1,:].shape, M[:,1].shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut assigner des nouvelles valeurs à certaines cellules :" ] }, { "cell_type": "code", "execution_count": 257, "metadata": { "collapsed": false }, "outputs": [], "source": [ "M[0,0] = 1" ] }, { "cell_type": "code", "execution_count": 258, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1. , 0.78556744, 0.74477941],\n", " [0.86289541, 0.21311052, 0.19970051],\n", " [0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 258, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "code", "execution_count": 259, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# on peut aussi assigner des lignes ou des colonnes\n", "M[1,:] = -1\n", "# M[1,:] = [1, 2, 3]" ] }, { "cell_type": "code", "execution_count": 260, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1. , 0.78556744, 0.74477941],\n", " [-1. , -1. , -1. ],\n", " [ 0.83596086, 0.16492924, 0.5769627 ]])" ] }, "execution_count": 260, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### *Slicing* ou accès par tranches\n", "\n", "*Slicing* fait référence à la syntaxe `M[start:stop:step]` pour extraire une partie d'un *array* :" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 261, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([1, 2, 3, 4, 5])" ] }, "execution_count": 261, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([1,2,3,4,5])\n", "A" ] }, { "cell_type": "code", "execution_count": 262, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([2, 3])" ] }, "execution_count": 262, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les tranches sont modifiables :" ] }, { "cell_type": "code", "execution_count": 263, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, -2, -3, 4, 5])" ] }, "execution_count": 263, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1:3] = [-2,-3]\n", "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut omettre n'importe lequel des argument dans `M[start:stop:step]`:" ] }, { "cell_type": "code", "execution_count": 264, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, -2, -3, 4, 5])" ] }, "execution_count": 264, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[::] # indices de début, fin, et pas avec leurs valeurs par défaut" ] }, { "cell_type": "code", "execution_count": 265, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, -3, 5])" ] }, "execution_count": 265, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[::2] # pas = 2, indices de début et de fin par défaut" ] }, { "cell_type": "code", "execution_count": 266, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, -2, -3])" ] }, "execution_count": 266, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[:3] # les trois premiers éléments" ] }, { "cell_type": "code", "execution_count": 267, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([4, 5])" ] }, "execution_count": 267, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[3:] # à partir de l'indice 3" ] }, { "cell_type": "code", "execution_count": 268, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2]\n", " [ 3 4 5]\n", " [ 6 7 8]\n", " [ 9 10 11]]\n" ] } ], "source": [ "M = np.arange(12).reshape(4, 3)\n", "print( M)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut utiliser des indices négatifs :" ] }, { "cell_type": "code", "execution_count": 269, "metadata": { "collapsed": false }, "outputs": [], "source": [ "A = np.array([1,2,3,4,5])" ] }, { "cell_type": "code", "execution_count": 270, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 270, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[-1] # le dernier élément" ] }, { "cell_type": "code", "execution_count": 271, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([3, 4, 5])" ] }, "execution_count": 271, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[-3:] # les 3 derniers éléments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le *slicing* fonctionne de façon similaire pour les *array* multi-dimensionnels" ] }, { "cell_type": "code", "execution_count": 272, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3, 4],\n", " [10, 11, 12, 13, 14],\n", " [20, 21, 22, 23, 24],\n", " [30, 31, 32, 33, 34],\n", " [40, 41, 42, 43, 44]])" ] }, "execution_count": 272, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n", "\n", "A" ] }, { "cell_type": "code", "execution_count": 273, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[11, 12, 13],\n", " [21, 22, 23],\n", " [31, 32, 33]])" ] }, "execution_count": 273, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[1:4, 1:4] # sous-tableau" ] }, { "cell_type": "code", "execution_count": 274, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 2, 4],\n", " [20, 22, 24],\n", " [40, 42, 44]])" ] }, "execution_count": 274, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# sauts\n", "A[::2, ::2]" ] }, { "cell_type": "code", "execution_count": 275, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3, 4],\n", " [10, 11, 12, 13, 14],\n", " [20, 21, 22, 23, 24],\n", " [30, 31, 32, 33, 34],\n", " [40, 41, 42, 43, 44]])" ] }, "execution_count": 275, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 276, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3, 4],\n", " [10, 11, 12, 13, 14],\n", " [30, 31, 32, 33, 34]])" ] }, "execution_count": 276, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A[[0, 1, 3]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Indexation avancée (*fancy indexing*)\n", "\n", "Lorsque qu'on utilise des listes ou des *array* pour définir des tranches : " ] }, { "cell_type": "code", "execution_count": 277, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n", "\n", "\n", "[[10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [40 41 42 43 44]]\n" ] } ], "source": [ "row_indices = [1, 2, 4]\n", "print( A)\n", "print(\"\\n\")\n", "print ( A[row_indices])\n", "# print( A.shape)" ] }, { "cell_type": "code", "execution_count": 278, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n" ] } ], "source": [ "A[[1, 2]][:, [3, 4]] = 0 # ATTENTION !\n", "print( A)" ] }, { "cell_type": "code", "execution_count": 279, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[13 24]\n" ] } ], "source": [ "print ( A[[1, 2], [3, 4]])" ] }, { "cell_type": "code", "execution_count": 280, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 0 0]\n", " [20 21 22 0 0]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n" ] } ], "source": [ "A[np.ix_([1, 2], [3, 4])] = 0\n", "print ( A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut aussi utiliser des masques binaires :" ] }, { "cell_type": "code", "execution_count": 281, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 4])" ] }, "execution_count": 281, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = np.arange(5)\n", "B" ] }, { "cell_type": "code", "execution_count": 282, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 2]\n", "[0 2]\n" ] } ], "source": [ "row_mask = np.array([True, False, True, False, False])\n", "print( B[row_mask])\n", "print( B[[0,2]])" ] }, { "cell_type": "code", "execution_count": 283, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 2])" ] }, "execution_count": 283, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# de façon équivalente\n", "row_mask = np.array([1,0,1,0,0], dtype=bool)\n", "B[row_mask]" ] }, { "cell_type": "code", "execution_count": 284, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ True True False False False]\n", "[0 1]\n" ] } ], "source": [ "# ou encore\n", "a = np.array([1, 2, 3, 4, 5])\n", "print( a < 3)\n", "print( B[a < 3])" ] }, { "cell_type": "code", "execution_count": 285, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 0 0]\n", " [20 21 22 0 0]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]] \n", "\n", "[[ 0 1]\n", " [10 11]\n", " [20 21]\n", " [30 31]\n", " [40 41]]\n" ] } ], "source": [ "print( A,\"\\n\")\n", "print( A[:, a < 3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Opérations élément par élément" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On déclare aa et bb sur lesquelles nous allons illustrer quelques opérations" ] }, { "cell_type": "code", "execution_count": 286, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 1.]\n", " [1. 1.]\n", " [1. 1.]]\n" ] }, { "data": { "text/plain": [ "array([[0, 1],\n", " [2, 3],\n", " [4, 5]])" ] }, "execution_count": 286, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.ones((3,2))\n", "b = np.arange(6).reshape(a.shape)\n", "print(a)\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Les opérations arithmétiques avec les scalaires, ou entre arrays s'effectuent élément par élément. Lorsque le dtype n'est pas le même ( aa contient des float, bb contient des int), numpy adopte le type le plus \"grand\" (au sens de l'inclusion)." ] }, { "cell_type": "code", "execution_count": 287, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1. 4.]\n", " [ 9. 16.]\n", " [25. 36.]]\n", "[[3. 2.]\n", " [1. 0.]\n", " [1. 2.]]\n", "[[ 0.36787944 1. ]\n", " [ 2.71828183 7.3890561 ]\n", " [20.08553692 54.59815003]]\n" ] } ], "source": [ "print( (a + b)**2 )\n", "print( np.abs( 3*a - b ) )\n", "f = lambda x: np.exp(x-1)\n", "print( f(b) )" ] }, { "cell_type": "code", "execution_count": 288, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/2b/cj2pm60x61s5qlxpmr7g7km00000gn/T/ipykernel_6947/4032182506.py:1: RuntimeWarning: divide by zero encountered in true_divide\n", " 1/b\n" ] }, { "data": { "text/plain": [ "array([[ inf, 1. ],\n", " [0.5 , 0.33333333],\n", " [0.25 , 0.2 ]])" ] }, "execution_count": 288, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1/b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Broadcasting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Que se passe-t-il si les dimensions sont différentes?" ] }, { "cell_type": "code", "execution_count": 289, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1., 1., 1., 1.])" ] }, "execution_count": 289, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.ones(6)\n", "c" ] }, { "cell_type": "code", "execution_count": 290, "metadata": { "collapsed": false }, "outputs": [ { "ename": "ValueError", "evalue": "operands could not be broadcast together with shapes (3,2) (6,) ", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/2b/cj2pm60x61s5qlxpmr7g7km00000gn/T/ipykernel_6947/1847358893.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mb\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0mc\u001b[0m \u001b[0;31m# déclenche une exception\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 (3,2) (6,) " ] } ], "source": [ "b+c # déclenche une exception" ] }, { "cell_type": "code", "execution_count": 291, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0 1]\n", " [2 3]\n", " [4 5]]\n", "\n", "[[0]\n", " [1]\n", " [2]]\n" ] }, { "data": { "text/plain": [ "array([[0, 1],\n", " [3, 4],\n", " [6, 7]])" ] }, "execution_count": 291, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.arange(3).reshape((3,1))\n", "print(b,c, sep='\\n\\n')\n", "b+c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "L'opération précédente fonctionne car numpy effectue ce qu'on appelle un [broadcasting](https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) de c : une dimension étant commune, tout se passe comme si on dupliquait c sur la dimension non-partagée avec b. Vous trouverez une explication visuelle simple ici :" ] }, { "cell_type": "code", "execution_count": 292, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[-1. 1. 2.]\n", " [-1. 1. 2.]\n", " [-1. 1. 2.]]\n" ] } ], "source": [ "a = np.zeros((3,3))\n", "a[:,0] = -1\n", "b = np.array(range(3))\n", "print(a + b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Extraction de données à partir d'*arrays* et création d'*arrays*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### where\n", "\n", "Un masque binaire peut être converti en indices de positions avec `where`" ] }, { "cell_type": "code", "execution_count": 293, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8. 8.5\n", " 9. 9.5]\n", "[False False False False False False False False False False False True\n", " True True True False False False False False]\n" ] }, { "data": { "text/plain": [ "(array([11, 12, 13, 14]),)" ] }, "execution_count": 293, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.arange(0, 10, 0.5)\n", "print ( x)\n", "mask = (x > 5) * (x < 7.5)\n", "print( mask)\n", "indices = np.where(mask)\n", "indices" ] }, { "cell_type": "code", "execution_count": 294, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([5.5, 6. , 6.5, 7. ])" ] }, "execution_count": 294, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x[indices] # équivalent à x[mask]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### diag\n", "\n", "Extraire la diagonale ou une sous-diagonale d'un *array* :" ] }, { "cell_type": "code", "execution_count": 295, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 0 0]\n", " [20 21 22 0 0]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n" ] }, { "data": { "text/plain": [ "array([ 0, 11, 22, 33, 44])" ] }, "execution_count": 295, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print ( A)\n", "np.diag(A)" ] }, { "cell_type": "code", "execution_count": 296, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([10, 21, 32, 43])" ] }, "execution_count": 296, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.diag(A, -1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Algèbre linéaire\n", "\n", "La performance des programmes écrit en Python/Numpy dépend de la capacité à vectoriser les calculs (les écrire comme des opérations sur des vecteurs/matrices) en évitant au maximum les boucles `for/while`.\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vous avez un éventail de fonctions pour faire de l'algèbre linéaire dans [numpy](https://docs.scipy.org/doc/numpy/reference/routines.linalg.html) ou dans [scipy](https://docs.scipy.org/doc/scipy/reference/linalg.html). Cela peut vous servir si vous cherchez à faire une décomposition matricielle particulière ([LU](https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.linalg.lu.html), [QR](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.qr.html), [SVD](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.svd.html),...), si vous vous intéressez aux valeurs propres d'une matrice, etc..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Opérations scalaires\n", "\n", "On peut effectuer les opérations arithmétiques habituelles pour multiplier, additionner, soustraire et diviser des *arrays* avec/par des scalaires :" ] }, { "cell_type": "code", "execution_count": 297, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2 3 4]\n" ] } ], "source": [ "v1 = np.arange(0, 5)\n", "print (v1)" ] }, { "cell_type": "code", "execution_count": 298, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 2, 4, 6, 8])" ] }, "execution_count": 298, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v1 * 2" ] }, { "cell_type": "code", "execution_count": 299, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([2, 3, 4, 5, 6])" ] }, "execution_count": 299, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v1 + 2" ] }, { "cell_type": "code", "execution_count": 300, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n" ] } ], "source": [ "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n", "print( A)" ] }, { "cell_type": "code", "execution_count": 301, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 2 4 6 8]\n", " [20 22 24 26 28]\n", " [40 42 44 46 48]\n", " [60 62 64 66 68]\n", " [80 82 84 86 88]]\n" ] } ], "source": [ "print( A * 2)" ] }, { "cell_type": "code", "execution_count": 302, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 3 4 5 6]\n", " [12 13 14 15 16]\n", " [22 23 24 25 26]\n", " [32 33 34 35 36]\n", " [42 43 44 45 46]]\n" ] } ], "source": [ "print( A + 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Opérations terme-à-terme sur les *arrays*\n", "\n", "Les opérations par défaut sont des opérations **terme-à-terme** :" ] }, { "cell_type": "code", "execution_count": 303, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n" ] } ], "source": [ "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n", "print ( A)" ] }, { "cell_type": "code", "execution_count": 304, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 4, 9, 16],\n", " [ 100, 121, 144, 169, 196],\n", " [ 400, 441, 484, 529, 576],\n", " [ 900, 961, 1024, 1089, 1156],\n", " [1600, 1681, 1764, 1849, 1936]])" ] }, "execution_count": 304, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A * A # multiplication terme-à-terme" ] }, { "cell_type": "code", "execution_count": 305, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0. , 5.5, 11. , 16.5, 22. ],\n", " [ 5.5, 11. , 16.5, 22. , 27.5],\n", " [11. , 16.5, 22. , 27.5, 33. ],\n", " [16.5, 22. , 27.5, 33. , 38.5],\n", " [22. , 27.5, 33. , 38.5, 44. ]])" ] }, "execution_count": 305, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(A + A.T) / 2" ] }, { "cell_type": "code", "execution_count": 306, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2 3 4]\n", "[ 0 1 4 9 16]\n" ] } ], "source": [ "print( v1)\n", "print( v1 * v1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En multipliant des *arrays* de tailles compatibles, on obtient des multiplications terme-à-terme par ligne :" ] }, { "cell_type": "code", "execution_count": 307, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "((5, 5), (5,))" ] }, "execution_count": 307, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.shape, v1.shape" ] }, { "cell_type": "code", "execution_count": 308, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n", "[0 1 2 3 4]\n", "[[ 0 1 4 9 16]\n", " [ 0 11 24 39 56]\n", " [ 0 21 44 69 96]\n", " [ 0 31 64 99 136]\n", " [ 0 41 84 129 176]]\n" ] } ], "source": [ "print( A)\n", "print( v1)\n", "print( A * v1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Algèbre matricielle\n", "\n", "Comment faire des multiplications de matrices ? Deux façons :\n", " \n", " * en utilisant les fonctions [dot](https://docs.scipy.org/doc/numpy/reference/generated/numpy.dot.html); \n", " * en utiliser le type [matrix](http://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html).\n" ] }, { "cell_type": "code", "execution_count": 309, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(5, 5)\n", "[[ 0 1 2 3 4]\n", " [10 11 12 13 14]\n", " [20 21 22 23 24]\n", " [30 31 32 33 34]\n", " [40 41 42 43 44]]\n", "\n" ] } ], "source": [ "print( A.shape)\n", "print( A)\n", "print( type(A))" ] }, { "cell_type": "code", "execution_count": 310, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 300 310 320 330 340]\n", " [1300 1360 1420 1480 1540]\n", " [2300 2410 2520 2630 2740]\n", " [3300 3460 3620 3780 3940]\n", " [4300 4510 4720 4930 5140]]\n", "[[ 0 1 4 9 16]\n", " [ 100 121 144 169 196]\n", " [ 400 441 484 529 576]\n", " [ 900 961 1024 1089 1156]\n", " [1600 1681 1764 1849 1936]]\n" ] } ], "source": [ "print( np.dot(A, A)) # multiplication matrice\n", "print( A * A ) # multiplication élément par élément" ] }, { "cell_type": "code", "execution_count": 311, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 30, 130, 230, 330, 430])" ] }, "execution_count": 311, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.dot(v1)" ] }, { "cell_type": "code", "execution_count": 312, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 312, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.dot(v1, v1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Avec le type [matrix](http://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html) de Numpy" ] }, { "cell_type": "code", "execution_count": 313, "metadata": { "collapsed": false }, "outputs": [], "source": [ "M = np.matrix(A)\n", "v = np.matrix(v1).T # en faire un vecteur colonne" ] }, { "cell_type": "code", "execution_count": 314, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[ 30],\n", " [130],\n", " [230],\n", " [330],\n", " [430]])" ] }, "execution_count": 314, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M * v" ] }, { "cell_type": "code", "execution_count": 315, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[30]])" ] }, "execution_count": 315, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# produit scalaire\n", "v.T * v" ] }, { "cell_type": "code", "execution_count": 316, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[ 30],\n", " [131],\n", " [232],\n", " [333],\n", " [434]])" ] }, "execution_count": 316, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# avec les objets matrices, c'est les opérations standards sur les matrices qui sont appliquées\n", "v + M*v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si les dimensions sont incompatibles on provoque des erreurs :" ] }, { "cell_type": "code", "execution_count": 317, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v = np.matrix([1,2,3,4,5,6]).T" ] }, { "cell_type": "code", "execution_count": 318, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "((5, 5), (6, 1))" ] }, "execution_count": 318, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(M), np.shape(v)" ] }, { "cell_type": "code", "execution_count": 319, "metadata": { "collapsed": false }, "outputs": [ { "ename": "ValueError", "evalue": "shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/2b/cj2pm60x61s5qlxpmr7g7km00000gn/T/ipykernel_6947/2280171313.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/opt/anaconda3/lib/python3.8/site-packages/numpy/matrixlib/defmatrix.py\u001b[0m in \u001b[0;36m__mul__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 216\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndarray\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\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[1;32m 217\u001b[0m \u001b[0;31m# This promotes 1-D vectors to row vectors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 218\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0masmatrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\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[0m\u001b[1;32m 219\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misscalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'__rmul__'\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[1;32m 220\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)" ] } ], "source": [ "M * v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Voir également les fonctions : `inner`, `outer`, `cross`, `kron`, `tensordot`. Utiliser par exemple `help(kron)`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On peut calculer l'inverse ou le déterminant de $A$ " ] }, { "cell_type": "code", "execution_count": 320, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 0. 0.]\n", " [1. 1. 0.]\n", " [1. 1. 1.]]\n", "-------\n", "1.0\n", "-------\n", "[[ 1. 0. 0.]\n", " [-1. 1. 0.]\n", " [ 0. -1. 1.]]\n", "-------\n", "[[1. 0. 0.]\n", " [0. 1. 0.]\n", " [0. 0. 1.]]\n" ] } ], "source": [ "A = np.tril(np.ones((3,3)))\n", "b = np.diag([1,2, 3])\n", "print(A)\n", "print(\"-------\")\n", "print(np.linalg.det(A)) # déterminant de la matrice A\n", "print(\"-------\")\n", "inv_A = np.linalg.inv(A) # inverse de la matrice A\n", "print(inv_A)\n", "print(\"-------\")\n", "print(inv_A.dot(A))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... résoudre des systèmes d'equations linéaires du type $Ax=b$ ..." ] }, { "cell_type": "code", "execution_count": 321, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 2 3]\n", "[1. 1. 1.]\n", "[1. 2. 3.]\n" ] } ], "source": [ "x = np.linalg.solve(A, np.diag(b))\n", "print(np.diag(b))\n", "print(x)\n", "print(A.dot(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "... ou encore obtenir les valeurs propres de $A$" ] }, { "cell_type": "code", "execution_count": 322, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(array([1., 1., 1.]),\n", " array([[ 0.00000000e+00, 0.00000000e+00, 4.93038066e-32],\n", " [ 0.00000000e+00, 2.22044605e-16, -2.22044605e-16],\n", " [ 1.00000000e+00, -1.00000000e+00, 1.00000000e+00]]))" ] }, "execution_count": 322, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linalg.eig(A)" ] }, { "cell_type": "code", "execution_count": 323, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1.])" ] }, "execution_count": 323, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linalg.eigvals(A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Transformations d'*arrays* ou de matrices" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Plus haut `.T` a été utilisé pour transposer l'objet matrice `v`\n", " * On peut aussi utiliser la fonction `transpose`\n", "\n", "**Autres transformations :**\n" ] }, { "cell_type": "code", "execution_count": 324, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[0.+1.j, 0.+2.j],\n", " [0.+3.j, 0.+4.j]])" ] }, "execution_count": 324, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C = np.matrix([[1j, 2j], [3j, 4j]])\n", "C" ] }, { "cell_type": "code", "execution_count": 325, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[0.-1.j, 0.-2.j],\n", " [0.-3.j, 0.-4.j]])" ] }, "execution_count": 325, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.conjugate(C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Transposée conjuguée :" ] }, { "cell_type": "code", "execution_count": 326, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[0.-1.j, 0.-3.j],\n", " [0.-2.j, 0.-4.j]])" ] }, "execution_count": 326, "metadata": {}, "output_type": "execute_result" } ], "source": [ "C.H" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parties réelles et imaginaires :" ] }, { "cell_type": "code", "execution_count": 327, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[0., 0.],\n", " [0., 0.]])" ] }, "execution_count": 327, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.real(C) # same as: C.real" ] }, { "cell_type": "code", "execution_count": 328, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[1., 2.],\n", " [3., 4.]])" ] }, "execution_count": 328, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.imag(C) # same as: C.imag" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Argument et module :" ] }, { "cell_type": "code", "execution_count": 329, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[0.78539816, 1.10714872],\n", " [1.24904577, 1.32581766]])" ] }, "execution_count": 329, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.angle(C+1) " ] }, { "cell_type": "code", "execution_count": 330, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "matrix([[1., 2.],\n", " [3., 4.]])" ] }, "execution_count": 330, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.abs(C)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Caclul matriciel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Analyse de données\n", "\n", "Numpy propose des fonctions pour calculer certaines statistiques des données stockées dans des *arrays* :" ] }, { "cell_type": "code", "execution_count": 331, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 1 1 1]\n", " [ 8 4 2 1]\n", " [27 9 3 1]\n", " [64 16 4 1]]\n", "(4, 4)\n" ] } ], "source": [ "data = np.vander([1, 2, 3, 4])\n", "print( data)\n", "print( data.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### mean" ] }, { "cell_type": "code", "execution_count": 332, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[25. 7.5 2.5 1. ]\n" ] } ], "source": [ "# np.mean(data)\n", "print( np.mean(data, axis=0))" ] }, { "cell_type": "code", "execution_count": 333, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2.5" ] }, "execution_count": 333, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# la moyenne de la troisième colonne\n", "np.mean(data[:,2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### variance et écart type" ] }, { "cell_type": "code", "execution_count": 334, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1.25, 1.118033988749895)" ] }, "execution_count": 334, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.var(data[:,2]), np.std(data[:,2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### min et max" ] }, { "cell_type": "code", "execution_count": 335, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 335, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data[:,2].min()" ] }, { "cell_type": "code", "execution_count": 336, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 336, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data[:,2].max()" ] }, { "cell_type": "code", "execution_count": 337, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 337, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data[:,2].sum()" ] }, { "cell_type": "code", "execution_count": 338, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "24" ] }, "execution_count": 338, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data[:,2].prod()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### sum, prod, et trace" ] }, { "cell_type": "code", "execution_count": 339, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ] }, "execution_count": 339, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = np.arange(0, 10)\n", "d" ] }, { "cell_type": "code", "execution_count": 340, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "45" ] }, "execution_count": 340, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# somme des éléments\n", "np.sum(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ou encore :" ] }, { "cell_type": "code", "execution_count": 341, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "45" ] }, "execution_count": 341, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.sum()" ] }, { "cell_type": "code", "execution_count": 342, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3628800" ] }, "execution_count": 342, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# produit des éléments\n", "np.prod(d+1)" ] }, { "cell_type": "code", "execution_count": 343, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])" ] }, "execution_count": 343, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# somme cumulée\n", "np.cumsum(d)" ] }, { "cell_type": "code", "execution_count": 344, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 2, 6, 24, 120, 720, 5040,\n", " 40320, 362880, 3628800])" ] }, "execution_count": 344, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# produit cumulé\n", "np.cumprod(d+1)" ] }, { "cell_type": "code", "execution_count": 345, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "9" ] }, "execution_count": 345, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# équivalent à diag(A).sum()\n", "np.trace(data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Calculs avec parties d'*arrays*\n", "\n", "en utilisant l'indexation ou n'importe quelle méthode d'extraction de donnés à partir des *arrays*" ] }, { "cell_type": "code", "execution_count": 346, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, 1, 1, 1],\n", " [ 8, 4, 2, 1],\n", " [27, 9, 3, 1],\n", " [64, 16, 4, 1]])" ] }, "execution_count": 346, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data" ] }, { "cell_type": "code", "execution_count": 347, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 4, 9, 16])" ] }, "execution_count": 347, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.unique(data[:,1]) " ] }, { "cell_type": "code", "execution_count": 348, "metadata": { "collapsed": false }, "outputs": [], "source": [ "mask = data[:,1] == 4" ] }, { "cell_type": "code", "execution_count": 349, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 349, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.mean(data[mask,3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Calculs avec données multi-dimensionnelles\n", "\n", "Pour appliquer `min`, `max`, etc., par lignes ou colonnes :" ] }, { "cell_type": "code", "execution_count": 350, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0.93442735, 0.87099207, 0.17577932, 0.67129581],\n", " [0.8198531 , 0.05267227, 0.99672342, 0.69230584],\n", " [0.29042857, 0.71206665, 0.67469746, 0.26979785]])" ] }, "execution_count": 350, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = random.rand(3,4)\n", "m" ] }, { "cell_type": "code", "execution_count": 351, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.996723416763222" ] }, "execution_count": 351, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# max global \n", "m.max()" ] }, { "cell_type": "code", "execution_count": 352, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.93442735, 0.87099207, 0.99672342, 0.69230584])" ] }, "execution_count": 352, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# max dans chaque colonne\n", "m.max(axis=0)" ] }, { "cell_type": "code", "execution_count": 353, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.93442735, 0.99672342, 0.71206665])" ] }, "execution_count": 353, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# max dans chaque ligne\n", "m.max(axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plusieurs autres méthodes des classes `array` et `matrix` acceptent l'argument (optional) `axis` keyword argument." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Génération de nombres aléatoires et statistiques" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le module : [numpy.random](https://docs.scipy.org/doc/numpy/reference/routines.random.html) apporte à python la possibilité de générer un échantillon de taille nn directement, alors que le module natif de python ne produit des tirages que un par un. Le module [numpy.random](https://docs.scipy.org/doc/numpy/reference/routines.random.html) est donc bien plus efficace si on veut tirer des échantillon conséquents. Par ailleurs, [scipy.stats](https://docs.scipy.org/doc/scipy/reference/stats.html) fournit des méthodes pour un très grand nombre de distributions et quelques fonctions classiques de statistiques.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Par exemple, on peut obtenir un array 4x3 de tirages gaussiens standard (soit en utilisant [randn](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randn.html#numpy.random.randn) ou [normal](https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.normal.html#numpy.random.normal) :" ] }, { "cell_type": "code", "execution_count": 354, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0.05524557, 0.55336726, -1.1627065 ],\n", " [-0.36085927, -0.54374562, -2.05864731],\n", " [-0.94184756, 1.68148183, 0.40946403],\n", " [ 0.64721499, -1.25286187, -1.91732065]])" ] }, "execution_count": 354, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.random.randn(4,3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour se convaincre que *numpy.random* est plus efficace que le module random de base de python. On effectue un grand nombre de tirages gaussiens standard, en python pur et via numpy." ] }, { "cell_type": "code", "execution_count": 355, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6.82 ms ± 573 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "N = int(1e4)\n", "from random import normalvariate\n", "%timeit [normalvariate(0,1) for _ in range(N)]" ] }, { "cell_type": "code", "execution_count": 356, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "334 µs ± 37.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit np.random.randn(N)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Copy et \"deep copy\"\n", "\n", "Pour des raisons de performance Python ne copie pas automatiquement les objets (par exemple passage par référence des paramètres de fonctions)." ] }, { "cell_type": "code", "execution_count": 357, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 2],\n", " [3, 4]])" ] }, "execution_count": 357, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A = np.array([[0, 2],[ 3, 4]])\n", "A" ] }, { "cell_type": "code", "execution_count": 358, "metadata": { "collapsed": false }, "outputs": [], "source": [ "B = A" ] }, { "cell_type": "code", "execution_count": 359, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 359, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# changer B affecte A\n", "B[0,0] = 10\n", "B" ] }, { "cell_type": "code", "execution_count": 360, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 360, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 361, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "B = A\n", "print( B is A)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour éviter ce comportement, on peut demander une *copie profonde* (*deep copy*) de `A` dans `B`" ] }, { "cell_type": "code", "execution_count": 362, "metadata": { "collapsed": false }, "outputs": [], "source": [ "#B = np.copy(A)\n", "B = A.copy()" ] }, { "cell_type": "code", "execution_count": 363, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[-5, 2],\n", " [ 3, 4]])" ] }, "execution_count": 363, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# maintenant en modifiant B, A n'est plus affecté\n", "B[0,0] = -5\n", "\n", "B" ] }, { "cell_type": "code", "execution_count": 364, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 364, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A # A est aussi modifié !" ] }, { "cell_type": "code", "execution_count": 365, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 -1]\n", " [-7 1]]\n", "[[ 0 -8]\n", " [ 0 1]]\n" ] } ], "source": [ "print( A - A[:,0] ) # FAUX\n", "print (A - A[:,0].reshape((2, 1))) # OK" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Changement de forme et de taille, et concaténation des *arrays*\n", "\n" ] }, { "cell_type": "code", "execution_count": 366, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 2],\n", " [ 3, 4]])" ] }, "execution_count": 366, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "code", "execution_count": 367, "metadata": { "collapsed": false }, "outputs": [], "source": [ "n, m = A.shape" ] }, { "cell_type": "code", "execution_count": 368, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[10, 2, 3, 4]])" ] }, "execution_count": 368, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = A.reshape((1,n*m))\n", "B" ] }, { "cell_type": "code", "execution_count": 369, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[5, 5, 5, 5]])" ] }, "execution_count": 369, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B[0,0:5] = 5 # modifier l'array\n", "\n", "B" ] }, { "cell_type": "code", "execution_count": 370, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[5, 5],\n", " [5, 5]])" ] }, "execution_count": 370, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Attention !\n", "\n", "La variable originale est aussi modifiée ! B n'est qu'une nouvelle *vue* de A." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour transformer un *array* multi-dimmensionel en un vecteur. Mais cette fois-ci, une copie des données est créée :" ] }, { "cell_type": "code", "execution_count": 371, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([5, 5, 5, 5])" ] }, "execution_count": 371, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B = A.flatten()\n", "B" ] }, { "cell_type": "code", "execution_count": 372, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([10, 10, 10, 10])" ] }, "execution_count": 372, "metadata": {}, "output_type": "execute_result" } ], "source": [ "B[0:5] = 10\n", "B" ] }, { "cell_type": "code", "execution_count": 373, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[5, 5],\n", " [5, 5]])" ] }, "execution_count": 373, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A # A ne change pas car B est une copie de A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ajouter une nouvelle dimension avec `newaxis`\n", "\n", "par exemple pour convertir un vecteur en une matrice ligne ou colonne :" ] }, { "cell_type": "code", "execution_count": 374, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v = np.array([1,2,3])" ] }, { "cell_type": "code", "execution_count": 375, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(3,)" ] }, "execution_count": 375, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.shape(v)" ] }, { "cell_type": "code", "execution_count": 376, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1],\n", " [2],\n", " [3]])" ] }, "execution_count": 376, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# créer une matrice à une colonne à partir du vectuer v\n", "v[:, np.newaxis]" ] }, { "cell_type": "code", "execution_count": 377, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(3, 1)" ] }, "execution_count": 377, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v[:,np.newaxis].shape" ] }, { "cell_type": "code", "execution_count": 378, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(1, 3)" ] }, "execution_count": 378, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# matrice à une ligne\n", "v[np.newaxis,:].shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Concaténer, répéter des *arrays*\n", "\n", "En utilisant les fonctions `repeat`, `tile`, `vstack`, `hstack`, et `concatenate`, on peut créer des vecteurs/matrices plus grandes à partir de vecteurs/matrices plus petites :\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### repeat et tile" ] }, { "cell_type": "code", "execution_count": 379, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [3, 4]])" ] }, "execution_count": 379, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([[1, 2], [3, 4]])\n", "a" ] }, { "cell_type": "code", "execution_count": 380, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])" ] }, "execution_count": 380, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# répéter chaque élément 3 fois\n", "np.repeat(a, 3) # résultat 1-d" ] }, { "cell_type": "code", "execution_count": 381, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 1, 1, 2, 2, 2],\n", " [3, 3, 3, 4, 4, 4]])" ] }, "execution_count": 381, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# on peut spécifier l'argument axis\n", "np.repeat(a, 3, axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour répéter la matrice, il faut utiliser `tile`" ] }, { "cell_type": "code", "execution_count": 382, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 1, 2, 1, 2],\n", " [3, 4, 3, 4, 3, 4]])" ] }, "execution_count": 382, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# répéter la matrice 3 fois\n", "np.tile(a, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### concatenate" ] }, { "cell_type": "code", "execution_count": 383, "metadata": { "collapsed": false }, "outputs": [], "source": [ "b = np.array([[5, 6]])" ] }, { "cell_type": "code", "execution_count": 384, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [3, 4],\n", " [5, 6]])" ] }, "execution_count": 384, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.concatenate((a, b), axis=0)" ] }, { "cell_type": "code", "execution_count": 385, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 5],\n", " [3, 4, 6]])" ] }, "execution_count": 385, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.concatenate((a, b.T), axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### hstack et vstack" ] }, { "cell_type": "code", "execution_count": 386, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [3, 4],\n", " [5, 6]])" ] }, "execution_count": 386, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.vstack((a,b))" ] }, { "cell_type": "code", "execution_count": 387, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 5],\n", " [3, 4, 6]])" ] }, "execution_count": 387, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.hstack((a,b.T))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Itérer sur les éléments d'un *array*\n", "\n", " * Dans la mesure du possible, il faut éviter l'itération sur les éléments d'un *array* : c'est beaucoup plus lent que les opérations vectorisées\n", " * Mais il arrive que l'on n'ait pas le choix..." ] }, { "cell_type": "code", "execution_count": 388, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "v = np.array([1,2,3,4])\n", "\n", "for element in v:\n", " print(element)" ] }, { "cell_type": "code", "execution_count": 389, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "row [1 2]\n", "1\n", "2\n", "row [3 4]\n", "3\n", "4\n" ] } ], "source": [ "M = np.array([[1,2], [3,4]])\n", "\n", "for row in M:\n", " print (\"row\", row)\n", " \n", " for element in row:\n", " print( element)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pour obtenir les indices des éléments sur lesquels on itère (par exemple, pour pouvoir les modifier en même temps) on peut utiliser `enumerate` :" ] }, { "cell_type": "code", "execution_count": 390, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "row_idx 0 row [1 2]\n", "col_idx 0 element 1\n", "col_idx 1 element 2\n", "row_idx 1 row [3 4]\n", "col_idx 0 element 3\n", "col_idx 1 element 4\n" ] } ], "source": [ "for row_idx, row in enumerate(M):\n", " print (\"row_idx\", row_idx, \"row\", row)\n", " \n", " for col_idx, element in enumerate(row):\n", " print( \"col_idx\", col_idx, \"element\", element)\n", " \n", " # update the matrix M: square each element\n", " M[row_idx, col_idx] = element ** 2" ] }, { "cell_type": "code", "execution_count": 391, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, 4],\n", " [ 9, 16]])" ] }, "execution_count": 391, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# chaque élément de M a maintenant été élevé au carré\n", "M" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Utilisation d'*arrays* dans des conditions\n", "\n", "Losqu'on s'intéresse à des conditions sur tout on une partie d'un *array*, on peut utiliser `any` ou `all` :" ] }, { "cell_type": "code", "execution_count": 392, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, 4],\n", " [ 9, 16]])" ] }, "execution_count": 392, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M" ] }, { "cell_type": "code", "execution_count": 393, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "au moins un élément de M est plus grand que 5\n" ] } ], "source": [ "if (M > 5).any():\n", " print( \"au moins un élément de M est plus grand que 5\")\n", "else:\n", " print (\"aucun élément de M n'est plus grand que 5\")" ] }, { "cell_type": "code", "execution_count": 394, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tous les éléments de M sont plus petits que 5\n" ] } ], "source": [ "if (M > 5).all():\n", " print (\"tous les éléments de M sont plus grands que 5\")\n", "else:\n", " print( \"tous les éléments de M sont plus petits que 5\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### *Type casting*\n", "\n", "On peut créer une vue d'un autre type que l'original pour un *array*" ] }, { "cell_type": "code", "execution_count": 395, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dtype('int64')" ] }, "execution_count": 395, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M =np.array([[-1,2], [0,4]])\n", "M.dtype" ] }, { "cell_type": "code", "execution_count": 396, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[-1., 2.],\n", " [ 0., 4.]])" ] }, "execution_count": 396, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M2 = M.astype(float)\n", "M2" ] }, { "cell_type": "code", "execution_count": 397, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "dtype('float64')" ] }, "execution_count": 397, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M2.dtype" ] }, { "cell_type": "code", "execution_count": 398, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ True, True],\n", " [False, True]])" ] }, "execution_count": 398, "metadata": {}, "output_type": "execute_result" } ], "source": [ "M3 = M.astype(bool)\n", "M3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pour aller plus loin\n", "\n", "* http://numpy.scipy.org\n", "* http://scipy.org/Tentative_NumPy_Tutorial" ] } ], "metadata": { "anaconda-cloud": {}, "interpreter": { "hash": "40d3a090f54c6569ab1632332b64b2c03c39dcf918b08424e98f38b5ae0af88f" }, "kernelspec": { "display_name": "Python [Root]", "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.8" } }, "nbformat": 4, "nbformat_minor": 0 }