4.1. Création d’un tableau#

Le module numpy est un outil performant pour la manipulation de tableaux à plusieurs dimensions. Il ajoute en effet la classe array qui a des similarités avec les listes mais tous les éléments sont obligatoirement du même type : soit des entiers, soit des flotants, soit des booléens…

Nous commençons par charger le module numpy et nous lui donnons un alias pour raccourcir son appel (l’alias np n’est pas obligatoire mais dans la pratique, tout le monde l’utilise).

import numpy as np
help(np.array)
Help on built-in function array in module numpy:

array(...)
    array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0,
          like=None)
    
    Create an array.
    
    Parameters
    ----------
    object : array_like
        An array, any object exposing the array interface, an object whose
        ``__array__`` method returns an array, or any (nested) sequence.
        If object is a scalar, a 0-dimensional array containing object is
        returned.
    dtype : data-type, optional
        The desired data-type for the array. If not given, NumPy will try to use
        a default ``dtype`` that can represent the values (by applying promotion
        rules when necessary.)
    copy : bool, optional
        If true (default), then the object is copied.  Otherwise, a copy will
        only be made if ``__array__`` returns a copy, if obj is a nested
        sequence, or if a copy is needed to satisfy any of the other
        requirements (``dtype``, ``order``, etc.).
    order : {'K', 'A', 'C', 'F'}, optional
        Specify the memory layout of the array. If object is not an array, the
        newly created array will be in C order (row major) unless 'F' is
        specified, in which case it will be in Fortran order (column major).
        If object is an array the following holds.
    
        ===== ========= ===================================================
        order  no copy                     copy=True
        ===== ========= ===================================================
        'K'   unchanged F & C order preserved, otherwise most similar order
        'A'   unchanged F order if input is F and not C, otherwise C order
        'C'   C order   C order
        'F'   F order   F order
        ===== ========= ===================================================
    
        When ``copy=False`` and a copy is made for other reasons, the result is
        the same as if ``copy=True``, with some exceptions for 'A', see the
        Notes section. The default order is 'K'.
    subok : bool, optional
        If True, then sub-classes will be passed-through, otherwise
        the returned array will be forced to be a base-class array (default).
    ndmin : int, optional
        Specifies the minimum number of dimensions that the resulting
        array should have.  Ones will be prepended to the shape as
        needed to meet this requirement.
    like : array_like, optional
        Reference object to allow the creation of arrays which are not
        NumPy arrays. If an array-like passed in as ``like`` supports
        the ``__array_function__`` protocol, the result will be defined
        by it. In this case, it ensures the creation of an array object
        compatible with that passed in via this argument.
    
        .. versionadded:: 1.20.0
    
    Returns
    -------
    out : ndarray
        An array object satisfying the specified requirements.
    
    See Also
    --------
    empty_like : Return an empty array with shape and type of input.
    ones_like : Return an array of ones with shape and type of input.
    zeros_like : Return an array of zeros with shape and type of input.
    full_like : Return a new array with shape of input filled with value.
    empty : Return a new uninitialized array.
    ones : Return a new array setting values to one.
    zeros : Return a new array setting values to zero.
    full : Return a new array of given shape filled with value.
    
    
    Notes
    -----
    When order is 'A' and ``object`` is an array in neither 'C' nor 'F' order,
    and a copy is forced by a change in dtype, then the order of the result is
    not necessarily 'C' as expected. This is likely a bug.
    
    Examples
    --------
    >>> np.array([1, 2, 3])
    array([1, 2, 3])
    
    Upcasting:
    
    >>> np.array([1, 2, 3.0])
    array([ 1.,  2.,  3.])
    
    More than one dimension:
    
    >>> np.array([[1, 2], [3, 4]])
    array([[1, 2],
           [3, 4]])
    
    Minimum dimensions 2:
    
    >>> np.array([1, 2, 3], ndmin=2)
    array([[1, 2, 3]])
    
    Type provided:
    
    >>> np.array([1, 2, 3], dtype=complex)
    array([ 1.+0.j,  2.+0.j,  3.+0.j])
    
    Data-type consisting of more than one element:
    
    >>> x = np.array([(1,2),(3,4)],dtype=[('a','<i4'),('b','<i4')])
    >>> x['a']
    array([1, 3])
    
    Creating an array from sub-classes:
    
    >>> np.array(np.mat('1 2; 3 4'))
    array([[1, 2],
           [3, 4]])
    
    >>> np.array(np.mat('1 2; 3 4'), subok=True)
    matrix([[1, 2],
            [3, 4]])

Interdit

Vous verrez souvent l’importation sous la forme

from numpy import *

C’est dangereux pour plusieurs raisons

  1. cela place touts les objets créés dans numpy dans l’espace de nom, quitte à écraser des choses que vous avez pu y mettre avant, ou pire, vous pouvez écraser des objets numpy sans le faire exprès ensuite…

  2. c’est très lourd car en général, vous n’avez pas besoin de charger tous les objets, seulement quelques uns.

  3. Dans la documentation python, cette syntaxe est réservée au développeur d’un module, c’est interdit pour les utilisateurs. Mais en python, tout est ouvert !

##############     INTERDIT     ##################
from numpy import *

print(exp(1))

def exp(x):  # on écrase la fonction exponentielle de python
    return x

print(exp(1))
2.718281828459045
1
############## SYNTAXE CORRECTE ##################
import numpy as np
import math

print(np.exp(1))
print(math.exp(1))
print(exp(1))
2.718281828459045
2.718281828459045
1

4.1.1. … à partir d’une liste#

Cela permet en particulier de remplir à la main des petits tableaux ou bien d’utiliser de manière astucieuses la compréhension de liste. On utilise pour cela la commande array qui transforme une liste en un tableau.

Voici quelques exemples :

# création d'un tableau d'entiers
A = np.array([1, 2, 3])
print(type(A), A, A.dtype)

# création d'un tableau de réels
A = np.array([1., 2, 3])
print(type(A), A, A.dtype)
<class 'numpy.ndarray'> [1 2 3] int64
<class 'numpy.ndarray'> [1. 2. 3.] float64
# tableau à deux dimensions
A = np.array(
    [
        [1, 2, 3],
        [2, 3, 4]
    ]
)
print(A)
[[1 2 3]
 [2 3 4]]
# Avec compréhension de liste
A = np.array([k**2/2 for k in range(-3, 4)])
print(A)
[4.5 2.  0.5 0.  0.5 2.  4.5]
# Un exemple en dimension 2 pour faire une matrice
N = 10
B = np.array([
    [k*l for l in range(N+1)] for k in range(N+1)
])
print(B)
[[  0   0   0   0   0   0   0   0   0   0   0]
 [  0   1   2   3   4   5   6   7   8   9  10]
 [  0   2   4   6   8  10  12  14  16  18  20]
 [  0   3   6   9  12  15  18  21  24  27  30]
 [  0   4   8  12  16  20  24  28  32  36  40]
 [  0   5  10  15  20  25  30  35  40  45  50]
 [  0   6  12  18  24  30  36  42  48  54  60]
 [  0   7  14  21  28  35  42  49  56  63  70]
 [  0   8  16  24  32  40  48  56  64  72  80]
 [  0   9  18  27  36  45  54  63  72  81  90]
 [  0  10  20  30  40  50  60  70  80  90 100]]

4.1.2. … à partir de commandes toutes prêtes#

Il existe un grand nombre de tableaux connus que l’on peut créer à l’aide de commandes. Par exemple des tableaux vides, remplis de 0 ou de 1, des matrices diagonales, des nombres équirépartis entre 2 valeurs… Les commandes à connaitre sont les suivantes : (mais ce ne seront peut-être pas les seules que nous utiliserons !)

  • np.empty, np.zeros, np.ones, np.random.rand ;

  • np.eye, np.identity, np.diag, np.triu, np.tril ;

  • np.arange, np.linspace.

nx, ny = 5, 4
# tableaux à 1 dimension
print(np.empty((nx,)))
print(np.zeros((nx,)))
print(np.zeros(nx))
print(np.ones((nx,)))
print(np.ones(nx))
[ 1.    2.75  6.   10.75 17.  ]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
# tableaux à 2 dimensions
print(np.empty((nx, ny)))
print(np.zeros((nx, ny)))
print(np.ones((nx, ny)))
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 0. 0. 0.]]
[[1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]
 [1. 1. 1. 1.]]
# on peut ajouter des dimensions...
print(np.zeros((2, 2, 2)))
[[[0. 0.]
  [0. 0.]]

 [[0. 0.]
  [0. 0.]]]
# pour faire des tableaux alétoires
print(np.random.rand(5))
print(np.random.rand(5, 5))
[0.85954498 0.21746794 0.79150153 0.19093383 0.0806769 ]
[[0.08317723 0.52181931 0.16622842 0.62375554 0.60507569]
 [0.38867929 0.11316953 0.03358762 0.85741732 0.02151827]
 [0.21722901 0.43661586 0.14173333 0.07134532 0.4135922 ]
 [0.74214346 0.35579988 0.21248817 0.7786657  0.94222406]
 [0.42724428 0.30349238 0.45721447 0.82690077 0.55496278]]
help(np.zeros)
Help on built-in function zeros in module numpy:

zeros(...)
    zeros(shape, dtype=float, order='C', *, like=None)
    
    Return a new array of given shape and type, filled with zeros.
    
    Parameters
    ----------
    shape : int or tuple of ints
        Shape of the new array, e.g., ``(2, 3)`` or ``2``.
    dtype : data-type, optional
        The desired data-type for the array, e.g., `numpy.int8`.  Default is
        `numpy.float64`.
    order : {'C', 'F'}, optional, default: 'C'
        Whether to store multi-dimensional data in row-major
        (C-style) or column-major (Fortran-style) order in
        memory.
    like : array_like, optional
        Reference object to allow the creation of arrays which are not
        NumPy arrays. If an array-like passed in as ``like`` supports
        the ``__array_function__`` protocol, the result will be defined
        by it. In this case, it ensures the creation of an array object
        compatible with that passed in via this argument.
    
        .. versionadded:: 1.20.0
    
    Returns
    -------
    out : ndarray
        Array of zeros with the given shape, dtype, and order.
    
    See Also
    --------
    zeros_like : Return an array of zeros with shape and type of input.
    empty : Return a new uninitialized array.
    ones : Return a new array setting values to one.
    full : Return a new array of given shape filled with value.
    
    Examples
    --------
    >>> np.zeros(5)
    array([ 0.,  0.,  0.,  0.,  0.])
    
    >>> np.zeros((5,), dtype=int)
    array([0, 0, 0, 0, 0])
    
    >>> np.zeros((2, 1))
    array([[ 0.],
           [ 0.]])
    
    >>> s = (2,2)
    >>> np.zeros(s)
    array([[ 0.,  0.],
           [ 0.,  0.]])
    
    >>> np.zeros((2,), dtype=[('x', 'i4'), ('y', 'i4')]) # custom dtype
    array([(0, 0), (0, 0)],
          dtype=[('x', '<i4'), ('y', '<i4')])
help(np.eye)
Help on function eye in module numpy:

eye(N, M=None, k=0, dtype=<class 'float'>, order='C', *, like=None)
    Return a 2-D array with ones on the diagonal and zeros elsewhere.
    
    Parameters
    ----------
    N : int
      Number of rows in the output.
    M : int, optional
      Number of columns in the output. If None, defaults to `N`.
    k : int, optional
      Index of the diagonal: 0 (the default) refers to the main diagonal,
      a positive value refers to an upper diagonal, and a negative value
      to a lower diagonal.
    dtype : data-type, optional
      Data-type of the returned array.
    order : {'C', 'F'}, optional
        Whether the output should be stored in row-major (C-style) or
        column-major (Fortran-style) order in memory.
    
        .. versionadded:: 1.14.0
    like : array_like, optional
        Reference object to allow the creation of arrays which are not
        NumPy arrays. If an array-like passed in as ``like`` supports
        the ``__array_function__`` protocol, the result will be defined
        by it. In this case, it ensures the creation of an array object
        compatible with that passed in via this argument.
    
        .. versionadded:: 1.20.0
    
    Returns
    -------
    I : ndarray of shape (N,M)
      An array where all elements are equal to zero, except for the `k`-th
      diagonal, whose values are equal to one.
    
    See Also
    --------
    identity : (almost) equivalent function
    diag : diagonal 2-D array from a 1-D array specified by the user.
    
    Examples
    --------
    >>> np.eye(2, dtype=int)
    array([[1, 0],
           [0, 1]])
    >>> np.eye(3, k=1)
    array([[0.,  1.,  0.],
           [0.,  0.,  1.],
           [0.,  0.,  0.]])
import numpy as np
N = 5
A = 2*np.eye(N, N, k=0) - np.eye(N, N, k=-1) - np.eye(N, N, k=1)
print(A)
[[ 2. -1.  0.  0.  0.]
 [-1.  2. -1.  0.  0.]
 [ 0. -1.  2. -1.  0.]
 [ 0.  0. -1.  2. -1.]
 [ 0.  0.  0. -1.  2.]]
help(np.diag)
Help on _ArrayFunctionDispatcher in module numpy:

diag(v, k=0)
    Extract a diagonal or construct a diagonal array.
    
    See the more detailed documentation for ``numpy.diagonal`` if you use this
    function to extract a diagonal and wish to write to the resulting array;
    whether it returns a copy or a view depends on what version of numpy you
    are using.
    
    Parameters
    ----------
    v : array_like
        If `v` is a 2-D array, return a copy of its `k`-th diagonal.
        If `v` is a 1-D array, return a 2-D array with `v` on the `k`-th
        diagonal.
    k : int, optional
        Diagonal in question. The default is 0. Use `k>0` for diagonals
        above the main diagonal, and `k<0` for diagonals below the main
        diagonal.
    
    Returns
    -------
    out : ndarray
        The extracted diagonal or constructed diagonal array.
    
    See Also
    --------
    diagonal : Return specified diagonals.
    diagflat : Create a 2-D array with the flattened input as a diagonal.
    trace : Sum along diagonals.
    triu : Upper triangle of an array.
    tril : Lower triangle of an array.
    
    Examples
    --------
    >>> x = np.arange(9).reshape((3,3))
    >>> x
    array([[0, 1, 2],
           [3, 4, 5],
           [6, 7, 8]])
    
    >>> np.diag(x)
    array([0, 4, 8])
    >>> np.diag(x, k=1)
    array([1, 5])
    >>> np.diag(x, k=-1)
    array([3, 7])
    
    >>> np.diag(np.diag(x))
    array([[0, 0, 0],
           [0, 4, 0],
           [0, 0, 8]])
x = np.random.rand(5)
print(x)
A = np.diag(x) + np.diag(x[1:], k=1) + np.diag(x[1:], k=-1)
print(A)
[0.70498023 0.56704263 0.19277841 0.6465539  0.70100521]
[[0.70498023 0.56704263 0.         0.         0.        ]
 [0.56704263 0.56704263 0.19277841 0.         0.        ]
 [0.         0.19277841 0.19277841 0.6465539  0.        ]
 [0.         0.         0.6465539  0.6465539  0.70100521]
 [0.         0.         0.         0.70100521 0.70100521]]
# On peut aussi récupérer la partie triangulaire supérieure 
# (ou la partie triangulaire inférieure) d'une matrice

A = np.random.rand(5, 5)
print(np.triu(A))
print(np.triu(A, k=-1))
[[0.97266369 0.41618611 0.02448125 0.70002191 0.16375673]
 [0.         0.84143618 0.39129594 0.1946312  0.07440549]
 [0.         0.         0.48515467 0.69793087 0.91151479]
 [0.         0.         0.         0.98375133 0.01041365]
 [0.         0.         0.         0.         0.31280995]]
[[0.97266369 0.41618611 0.02448125 0.70002191 0.16375673]
 [0.44342782 0.84143618 0.39129594 0.1946312  0.07440549]
 [0.         0.39792463 0.48515467 0.69793087 0.91151479]
 [0.         0.         0.7966201  0.98375133 0.01041365]
 [0.         0.         0.         0.40983154 0.31280995]]
# points équi-répartis entre a et b par pas de dx : np.arange(a, b, dx)
print(np.arange(10))
print(np.arange(2, 10))
print(np.arange(2, 10, 0.5))

# N points équi-répartis entre a et b : np.linspace(a, b, N)
print(np.linspace(0, 1, 11))
print(np.linspace(0, 1, 10, endpoint=False))
[0 1 2 3 4 5 6 7 8 9]
[2 3 4 5 6 7 8 9]
[2.  2.5 3.  3.5 4.  4.5 5.  5.5 6.  6.5 7.  7.5 8.  8.5 9.  9.5]
[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]
[0.  0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]

4.1.3. … à partir d’une fonction#

Il est aussi possible de créer un tableau à partir d’une fonction sur les indices du tableau. Par exemple, pour un tableau de dimension 1

\[ x_i = \phi(i), \quad 0\leq i\leq N-1,\]

ou en dimension 2

\[ A_{i, j} = \phi(i, j), \quad 0\leq i, j\leq N-1.\]

On utilise pour le cela la commande np.fromfunction qui prend en argument une fonction (attention, par défaut les indices i, j, … passés en argument à la fonction sont des float) et la forme du tableau sous la forme d’un tuple.

i = np.arange(10)
print(3*i+1.)
print(np.fromfunction(lambda i: 3*i+1, (10,)))
[ 1.  4.  7. 10. 13. 16. 19. 22. 25. 28.]
[ 1.  4.  7. 10. 13. 16. 19. 22. 25. 28.]
N = 6
hilbert = lambda i, j: 1/(i+j+1)
print(np.fromfunction(hilbert, (N, N)))
[[1.         0.5        0.33333333 0.25       0.2        0.16666667]
 [0.5        0.33333333 0.25       0.2        0.16666667 0.14285714]
 [0.33333333 0.25       0.2        0.16666667 0.14285714 0.125     ]
 [0.25       0.2        0.16666667 0.14285714 0.125      0.11111111]
 [0.2        0.16666667 0.14285714 0.125      0.11111111 0.1       ]
 [0.16666667 0.14285714 0.125      0.11111111 0.1        0.09090909]]
x = np.arange(10)
print(np.fromfunction(lambda i, j: x[(i+j) % x.size], (x.size, x.size), dtype=int))
[[0 1 2 3 4 5 6 7 8 9]
 [1 2 3 4 5 6 7 8 9 0]
 [2 3 4 5 6 7 8 9 0 1]
 [3 4 5 6 7 8 9 0 1 2]
 [4 5 6 7 8 9 0 1 2 3]
 [5 6 7 8 9 0 1 2 3 4]
 [6 7 8 9 0 1 2 3 4 5]
 [7 8 9 0 1 2 3 4 5 6]
 [8 9 0 1 2 3 4 5 6 7]
 [9 0 1 2 3 4 5 6 7 8]]
help(np.fromfunction)
Help on function fromfunction in module numpy:

fromfunction(function, shape, *, dtype=<class 'float'>, like=None, **kwargs)
    Construct an array by executing a function over each coordinate.
    
    The resulting array therefore has a value ``fn(x, y, z)`` at
    coordinate ``(x, y, z)``.
    
    Parameters
    ----------
    function : callable
        The function is called with N parameters, where N is the rank of
        `shape`.  Each parameter represents the coordinates of the array
        varying along a specific axis.  For example, if `shape`
        were ``(2, 2)``, then the parameters would be
        ``array([[0, 0], [1, 1]])`` and ``array([[0, 1], [0, 1]])``
    shape : (N,) tuple of ints
        Shape of the output array, which also determines the shape of
        the coordinate arrays passed to `function`.
    dtype : data-type, optional
        Data-type of the coordinate arrays passed to `function`.
        By default, `dtype` is float.
    like : array_like, optional
        Reference object to allow the creation of arrays which are not
        NumPy arrays. If an array-like passed in as ``like`` supports
        the ``__array_function__`` protocol, the result will be defined
        by it. In this case, it ensures the creation of an array object
        compatible with that passed in via this argument.
    
        .. versionadded:: 1.20.0
    
    Returns
    -------
    fromfunction : any
        The result of the call to `function` is passed back directly.
        Therefore the shape of `fromfunction` is completely determined by
        `function`.  If `function` returns a scalar value, the shape of
        `fromfunction` would not match the `shape` parameter.
    
    See Also
    --------
    indices, meshgrid
    
    Notes
    -----
    Keywords other than `dtype` and `like` are passed to `function`.
    
    Examples
    --------
    >>> np.fromfunction(lambda i, j: i, (2, 2), dtype=float)
    array([[0., 0.],
           [1., 1.]])
    
    >>> np.fromfunction(lambda i, j: j, (2, 2), dtype=float)
    array([[0., 1.],
           [0., 1.]])
    
    >>> np.fromfunction(lambda i, j: i == j, (3, 3), dtype=int)
    array([[ True, False, False],
           [False,  True, False],
           [False, False,  True]])
    
    >>> np.fromfunction(lambda i, j: i + j, (3, 3), dtype=int)
    array([[0, 1, 2],
           [1, 2, 3],
           [2, 3, 4]])