{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutoriel numpy pour la création et la manipulation de base des matrices\n", "\n", "Commandes de base python notebook\n", "\n", "Pour executer une cellule : Shift + Entrée" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Import OK\n" ] } ], "source": [ "# gestion des bibliothèques externes\n", "import numpy as np\n", "print(\"Import OK\") # affichage en fin de boite pour visualiser que l'exécution a bien eu lieue" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Créations de matrice par différentes méthodes" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Création de vecteurs\n", "v1 = np.arange(0, 10, 1) # create a range\n", " # arguments: start, stop, step\n", "\n", "v1 = np.arange(0, 10) # with default step=1\n", "v1 = np.arange(10) # default start=0\n", "print(v1)\n", "\n", "v2 = np.linspace(0, 10, 15) # avec linspace, le début et la fin SONT inclus\n", "print(v2)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2 3 4 5 6 7 8 9]\n", "[0 1 2 3 4 5 6 7 8 9]\n" ] } ], "source": [ "# Création de matrices\n", "m0 = np.array([[1, 2], [3, 4]]) # matrice\n", " # matrice = vecteur de vecteurs\n", " \n", "# création de listes en utilisant des boucles imbriquées:\n", "mp = [[n+m*10 for n in range(5)] for m in range(5)]\n", "\n", "# création d'une structure numpy à partir d'une liste ou d'une liste de liste:\n", "mn = np.array([[n+m*10 for n in range(5)] for m in range(5)]) # ou np.array(mp)\n", "print(mn)\n", "\n", "m1 = np.ones((10,2)) # matrice de 1, argument = nuplet avec les dimensions\n", " # ATTENTION np.ones(10,2) ne marche pas\n", "\n", "m2 = np.zeros((5,4)) # matrice de 0\n", "m3 = np.eye(4) # matrice identité carrée, arg = dimension\n", "print(m3)\n", "m4 = np.random.rand(5,6) # matrice de nombres aléatoires indépendants, args = dimensions\n", "m5 = np.random.randn(5,6) # tirages selon une gaussienne(mu=0,var=1), args = dimensions\n", "print(m5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# concaténation de matrices\n", "m6 = np.vstack((np.array([[1, 2], [3, 4]]), np.ones((3,2))))\n", "m7 = np.vstack((np.array([1, 2, 3]), np.hstack((np.ones((3,2)), np.zeros((3,1))))))\n", "print(m6)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# jouer avec les types des éléments internes aux matrices\n", "# une matrice d'entier\n", "matInt = np.zeros((5,6), int) # matrice 5x6 de 0 (entiers)\n", "matBool = np.zeros((5,6), bool) # matrice 5x6 de False (booléens)\n", "matBool2 = np.ones((5,6), bool) # matrice 5x6 de True (booléens)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Récupération/affectation de valeurs" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# une matrice \n", "mat = np.ones((5,6)) \n", "mat[0,0] # récupération de la première valeur\n", "mat[0,:] # récupération de la première ligne\n", "mat[0,0:2] # récupération des valeurs d'indice 0 et 1\n", "# petites astuces supplémentaires\n", "mat[0,1:] # toute la ligne sauf la première case\n", "mat[0,:-1] # toute la ligne sauf la dernière case\n", "mat[0,:-2] # toute la ligne sauf les deux dernières cases\n", "\n", "A = np.array([1,2,3,4,5])\n", "A[1:3] # array([2, 3])\n", "\n", "# On peut omettre n'importe lequel des argument dans M[start:stop:step]:\n", "A[::] # indices de début, fin, et pas avec leurs valeurs par défaut\n", " # array([ 1, -2, -3, 4, 5])\n", "A[::2] # pas = 2, indices de début et de fin par défaut\n", " # array([ 1, -3, 5])\n", "A[:3] # les trois premiers éléments (indices 0,1,2)\n", " # array([ 1, -2, -3])\n", "A[3:] # à partir de l'indice 3\n", " # array([4, 5])\n", "\n", "# On peut utiliser des indices négatifs :\n", "A[-1] # le dernier élément\n", " # 5\n", "A[-3:] # les 3 derniers éléments\n", " # array([3, 4, 5])\n", " \n", "# Affectation:\n", "# une matrice d'entier\n", "mat = np.ones((5,6)) \n", "mat[0,0:2] = 1 # affectation en bloc\n", "mat[0,0:2] = np.zeros((1,2)) # affectation en bloc d'une autre matrice\n", "\n", "# Matrice VS vecteur !!\n", "A = np.random.rand(5,3) # matrice 5x3\n", "B = A[2,:] # extraction de la troisième ligne...\n", " # il s'agit d'un vecteur !!!\n", "B = A[2:3,:] # extraction de la troisième ligne...\n", " # mais il s'agit d'une matrice (transposable) !!!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tailles des matrices" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# pour une variable:\n", "mat.shape # (5,6)\n", "mat.shape[0] # 5\n", "mat.shape[1] # 6 \n", "n, m = mat.shape # retours multiples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Fonctions de base sur les matrices\n", "Additions, transposées etc..." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "ma = np.random.rand(5,6) \n", "# Transposition\n", "mat = ma.T # pour la transposée \n", "mat = ma.transpose(); # ou bien\n", "mat = np.transpose(ma); # ou bien\n", "# la plupart des fonctions numpy acceptent la syntaxe objet et la syntaxe non-objet." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# Addition / soustraction\n", "v1 = v1+ 3 # ou v1 += 3 % matrice + scalaire\n", " # changement sur les toutes les valeurs de v1\n", " # NB: le - fonctionne pareil\n", "\n", "# multiplication :\n", "# ATTENTION à *\n", "m1 = np.ones((10,1)) * np.array([1,2,3]) # Attention, produit matriciel\n", "m2 = np.ones((10,3)) * 2 # multiplication par un scalaire\n", "m3 = m1 * m2; # multiplication terme à terme \n", "# usage de .dot => toujours matriciel\n", "m1 = np.ones((10,1)).dot(np.array([[1,2,3]])) # Bien mieux: moins d'ambiguité!" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([0.21683966, 0.33965359, 0.32771824])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# recherche du min dans une matrice\n", "m1.min() # syntaxe objet\n", "np.min(m1) # autre syntaxe\n", "# distinction min/argmin\n", "m1.argmin()\n", "\n", "# travail en ligne/colonne\n", "m1 = np.random.rand(3,4)\n", "# array([[ 0.77846102, 0.22597046, 0.217657 , 0.28958186],\n", "# [ 0.02133707, 0.03258567, 0.81939161, 0.2834734 ],\n", "# [ 0.92120271, 0.68409416, 0.24285983, 0.61582659]])\n", "m1.argmin() # 4\n", "m1.argmin(0) # array([1, 1, 0, 1])\n", "m1.argmin(1) # array([2, 0, 2])\n", "\n", "# arrondis\n", "np.round(m1) \n", "np.ceil(m1) \n", "np.floor(m1)\n", "\n", "# tris\n", "np.sort(m1) # ligne par ligne\n", "np.sort(m1,0) # colonne par colonne\n", "np.sort(m1,1) # ligne par ligne\n", "\n", "# statistique de base\n", "m1.mean() # 0.427 -> sur toute la matrice\n", "m1.mean(0) # array([ 0.57366693, 0.31421676, 0.42663615, 0.39629395]) \n", " # colonne par colonne\n", "m1.mean(1) # ligne par ligne\n", "\n", "# m1.std...\n", "# m1.sum...\n", "# m1.prod...\n", "# m1.cumsum..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Jouons avec les minima\n", "\n", "Gestion particulière du minimum: on a souvent besoin de retourner la valeur minimum parmi 2. En C/JAVA/Matlab, cela est réalisé avec min... Pas en python! => minimum" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# entre 2 valeurs\n", "np.minimum(2,3) # 2\n", "# entre 2 matrices\n", "m1 = random.rand(3,4)\n", "m2 = random.rand(3,4) \n", "np.minimum(m1,m2) # matrice 3x4 contenant les valeurs min d'une comparaison terme à terme\n", "# entre une matrice et un scalaire: pour seuiller\n", "np.minimum(m1,0.5)\n", "# array([[ 0.5 , 0.22597046, 0.217657 , 0.28958186],\n", "# [ 0.02133707, 0.03258567, 0.5 , 0.2834734 ],\n", "# [ 0.5 , 0.5 , 0.24285983, 0.5 ]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## boucles avancées (bien pratiques)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "v0 =np.arange(10)\n", "v1 = np.random.rand(10)\n", "\n", "for val0, val1 in zip(v0, v1):\n", " print('indice ',val0, ' et valeur associée ', val1)\n", " \n", "# note: il était possible d'obtenir le même résultat avec enumerate:\n", "for i, val in enumerate(v1):\n", " print('indice ',i, ' et valeur associée ', val)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tests en bloc\n", "Exercice intéressant pour deux raisons\n", "1. connaitre cette syntaxe particulière\n", "1. comprendre les messages d'erreur lorsqu'on essaie de faire des tests sur une matrice sans ces instructions" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "m = np.array([[1, 2], [3, 4]])\n", "\n", "if (m>1).all():\n", " print(\"(1) sup to 1\")\n", "else:\n", " print(\"(1) NOT sup to 1\")\n", "\n", "if (m>1).any():\n", " print(\"(2) sup to 1\")\n", "else:\n", " print(\"(2) NOT sup to 1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Fonctions et vectorisation des fonctions de base\n", "Il est évidemment possible de définir des fonctions prenant des structures numpy en argument. Mais il est aussi possible de *vectoriser* une fonction qui n'était pas prévue pour fonctionner sur des matrices. Il s'agit d'une nouvelle manière d'éviter les boucles." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 0 0 1 1 1 1]\n" ] } ], "source": [ "def theta(x): # signature classique \n", " \"\"\" \n", " Scalar implemenation of the Heaviside step function.\n", " \"\"\"\n", " if x >= 0:\n", " return 1\n", " else:\n", " return 0\n", " \n", "theta_vec = np.vectorize(theta) # notation fonctionnelle (fonction sur des fonctions)\n", "res = theta_vec(np.array([-3,-2,-1,0,1,2,3]))\n", "print(res) # [0 0 0 1 1 1 1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vérification de l'état de la mémoire" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# dir() => donne aussi les variables d'environnement, il faut filter:\n", "print([s for s in dir() if '_' not in s])\n", "# pour connaitre le type:\n", "print([(s,eval('type({})'.format(s))) for s in dir() if '_' not in s])\n", "# les commandes who et whos sont élégantes mais ne marchent qu'en ipython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sauvegarde / chargement depuis numpy" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "np.savetxt(\"random-matrix.txt\", m5)\n", "# donne le fichier:\n", "# 1.000000000000000000e+00 2.000000000000000000e+00\n", "# 3.000000000000000000e+00 4.000000000000000000e+00\n", "np.savetxt(\"random-matrix.csv\", m5, fmt='%.5f', delimiter=',')\n", "# donne le fichier:\n", "# 1.00000,2.00000\n", "# 3.00000,4.00000" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## De numpy à python, usage de pickle\n", "\n", "loadtxt/savetxt: idéal pour numpy...\n", " * Chargement/sauvegarde des matrices, format lisible de l'extérieur si besoin\n", " * Echanges possibles avec d'autres langages: matlab, JAVA...\n", "... Mais pour le python en général, on préfère pickle\n", " * Serialization généralisé: pour les valeurs, les objets (dont les matrices), les listes, les dictionnaires...\n", " * Très facile à utiliser\n", " * Utilisé par tout le monde en python... Donc à connaitre\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import pickle as pkl # obligatoire pour pouvoir l'utiliser\n", "# sauvegarde d'un dictionnaire\n", "pkl.dump({\"m1\":m1, \"m2\":m2}, open(\"deuxmatrices.pkl\",\"wb\"))\n", "# chargement de données\n", "data = pkl.load(open('deuxmatrices.pkl','rb')) # attention à donner un file + option lecture (pas juste un nom de fichier)\n", "print(data['m1']) # accès standard dans les dictionnaires" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercices de synthèse\n", "### Génération de données\n", "\n", "Nous souhaitons créer une matrice 10x3 dont la première colonne contient les indices 1 à 10 dans l'ordre. La seconde colonne contiendra des nombres aléatoires entre 0 et 1. La troisième colonne ne contiendra que des 0.\n", "Vous ajouterez ensuite une ligne en haut de la matrice contenant les indices de colonne 1 à 3.\n", "NB: vous pouvez créer des matrices dans des matrices, c'est-à-dire faire appel à des fonctions dans les [].\n", "\n", "Exemple de résultat possible:\n", "\n", " 1.00000 2.00000 3.00000\n", " 1.00000 0.03479 0.00000\n", " 2.00000 0.66074 0.00000\n", " 3.00000 0.15187 0.00000\n", " 4.00000 0.03640 0.00000\n", " 5.00000 0.62497 0.00000\n", " 6.00000 0.54774 0.00000\n", " 7.00000 0.68919 0.00000\n", " 8.00000 0.86146 0.00000\n", " 9.00000 0.72030 0.00000\n", " 10.0000 0.84590 0.00000\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# a vous de jouer !\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Récupération de données 'réelles'\n", "\n", "Soit le jeu de données suivant:\n", "\n", " 14.5 8.5 \n", " 15.5 8.5\n", " 9 14.5\n", " 9.5 15.5\n", " 11 9.5 \n", " 3.5 6\n", " 11.5 11\n", " 8.5 5.5\n", " 3 2\n", " 17 12\n", " 6 13\n", " 10 12.5\n", " 10 4\n", " 11.5 5.5\n", " 13.5 8\n", "\n", "1. Copier ces valeurs (notes d'une classe sur deux épreuves) dans un fichier 'college.dat'\n", "2. Importer ces valeurs dans une matrice numpy" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Génération de notes\n", "\n", "Nous souhaitons générer aléatoirement les notes de la question précédente sachant que:\n", "* Le nombre d'élèves est n=15\n", "* Les notes sont tirées selon une loi gaussienne d'écart-type 4. \n", " * Utiliser la commande np.random.randn pour générer les tirages puis multiplier par l'écart-type.\n", "* La première épreuve à une moyenne approximative de 10, la seconde, une moyenne de 8 (on veut donc décaler la première colonne de 10 et la seconde de 8)\n", "* On veut être sûr que les notes sont supérieures ou égales à 0 (utiliser maximum)\n", "* On veut être sûr que les notes sont inférieures ou égales à 20 (utiliser minimum)\n", "* On veut des notes entières (utiliser round)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Traduction de matrice\n", "* Générer une matrice aléatoire `m` de taille (15,2) contenant des indices aléatoires entre 0 et 3.\n", "* Construire le dictionnaire `dico` {1:'titi', 2:'toto', ...}\n", "* La méthode `get` du dictionnaire permet de traduire une valeur de `m`\n", "* Utiliser la commande `np.vectorize` pour traduire en une ligne et sans boucle toute la matrice `m` en une matrice `mtxt`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.0" } }, "nbformat": 4, "nbformat_minor": 2 }