Xavier Lamorlette

Python : mathématiques

Sommaire :

Nombres imaginaires

a = 1.5 + 1j
a.real -> 1.5
a.image -> 1.0
type(a) -> complex

Numpy

Numpy signifie “numeric python”.
Numpy permet principalement de manipuler des tableaux, sur lesquels on peut faire des opérations vectorisées (performantes).

ndarray

Un ndarray est un tableau dont les données sont contiguës en mémoire.
Il peut être construit via array(). Il contient un seul type de données, à spécifier via le paramètre dtype.
On peut appliquer directement sur les données des ndarray les “universal functions (ufunc)”.
Exemple :

sudo apt-get install python-numpy
sudo apt-get install python-matplotlib

import numpy as np
import matplotlib.pyplot as plt

v = np.array([1, 3, 2, 4])
plt.figure()
plt.plot(v)
plt.show()

plt.ion()  # mode interactif : pas la peine d'appeler show()

X = np.linspace(0., 10., 50)  # créer un intervale entre 0 et 10 avec 50 éléments
Y = np.cos(Y)
plt.plot(X, Y);

Sur un ndarray, on peut faire :

vectorise

vectorise est un décorateur qui transforme une fonction scalaire en une ufunc :

@np.vectorize
def a_function(x):
    return x**2 + 2*x

X = np.linspace(-5, 5)
Y = a_function(X)
plt.plot(X, Y);

Types

Les types Numpy (notamment utilisés via le paramètre dtype pour construire un array) permettent aussi d'avoir en Python des types dont on contrôle plus finement la taille (par exemple des entiers sur un octet).

Matplotlib

Matplotlib permet de faires des graphiques, avec une syntaxe très proche de Matlab.

Pandas

Pandas signifie “panel data”.
Pandas permet de rajouter des index aux tableaux Numpy et de faire de l'analyse de données avec des opérations de jointure, pivot, regroupement, etc.

Series

Une Series est un tableau Numpy à une dimension avec un label par valeur.
Ces labels permettent d'accéder aux valeurs comme pour un dictionnaire, et de faire du slicing comme pour une liste.
On utilise loc[] pour accéder aux valeurs via les labels, et iloc[] pour accéder aux valeurs via les positions.

Dataframe

Une Dataframe est un tableau à deux dimensions avec des labels sur les lignes et les colonnes.
On peut faire sur les Datafranme des opérations de concaténation, jointure, regroupement et pivot.

Exemples

Distributions et environnements recommandés :

v = np.array([1, 3, 2, 4])
plt.figure()
plt.plot(v)
plt.show()

plt.ion()  # mode interactif : pas la peine d'appeler show()

x_array = np.linspace(0., 10., 50)  # créer un intervale entre 0 et 10 avec 50 éléments
y_array = np.cos(y)
plt.plot(x_array, y_array);

x = np.array([0,2,4,6])
plt.figure()
plt.plot(x, v, "r--", label='vecteur')
plt.xlabel('x')
plt.ylabel('v')
plt.title('Titre')
plt.legend(loc='lower right')
plt.show()

M = np.array([[1, 3], [2, 4]])
M.shape -> (2, 2)
M.ndim -> 2
M.size -> 4
M.dtype -> int64 => tous les éléments de meme type, pas comme une liste !
M.itemsize -> 8
M.nbytes -> 32
M.nbytes / M.size => M.itemsize -> 8

a = np.array([0, 0, 0], dtype=np.float64)
a[0] = 3.2 -> OK, pas de troncage
dtype: int / float / complex / bool / object / int32 / int16 / float128 / complex128 etc.

M = np.array([[-1, 2], [0, 4]])
M2 = M.astype(float) -> conversion

x = np.array((range(0, 10, 2))
x = np.arange(0, 10, 2) -> pareil mais plus efficace
x = np.arange(-1, 1, 0.5)
np.linspace(0, 10, 6) -> 6 éléments régulièrement espacés entre 0 et 10 inclus

x = np.linspace(-10, 10, 100)
y = np.sin(x)
plt.plot(x, y, label='$y = \sin(x)$')
plt.legend()
plt.show()

a = np.arange(5, dtype=float)
a + 1 -> ajoute 1 à tous les éléments
2 * a
a ** 2
a + a -> addition élément par élément
a * a
// -> forcer la division entière

from numpy import random
random.random_sample((3, 3)) -> tirage uniforme dans [0, 1]
(comme random.rand)
random.standard_normal((3, 3)) -> tirage suivant une loi normale standard
(comme random.randn)

a = random.standard_normal(10000)
hh = plt.hist(a, 40) -> histogramme à 40 barres

C = random.standard_normal((32, 32))
plt.imshow(C, interpolation='nearest')
plt.colorbar()
plt.show()

A = np.zeros((2, 3)) -> remplit avec des flot64 = 0
A = np.zeros((2, 3), dtype=int)
np.ones((3, 3))

D = n.diag([1, 2, 3]) -> matrice diagonale
np.diag(D) -> extraction de la diagonale

data = np.genfromtxt('data.csv', delimiter=',') -> lecture depuis un CSV dans une matrice
np.savetxt("toto.csv", M, fmt=' % 2.3f', delimiter=',')
np.save("toto.npy", M) -> fichier binaire numpy
np.load("toto.npy")

M[1, :] -> équivalent de M[1] : 2ème ligne
M[:, 1] -> 2ème colonne
M[1, :] = -1 -> assigne à toute la ligne
M[:, 1] = [5, 6] -> change la colonne

slicing : M [start:stop:step]
A = np.array([1, 2, 3, 4, 5])
A[1:3] -> [2 3]
A[-1] -> dernier élément
A[-3:] -> 3 derniers éléments
A[1:3, 1:3] -> bloc du tableau

fancy indexing:
indices = [1, 3]
A[indices] -> lignes d'indices 1 et 3
A[:, indices] -> colonnes d'indices 1 et 3
A[[0, 2], [1, 3]]
A[np.ix_([0, 2], [1, 3])] -> sous-tableau lignes 0 et 1 et colonnes 2 et 3

indexation avec masques booléens
v = np.arange(5)
v > 2 -> [False False False True True]
v[v > 2] -> [3 4]

A.T -> transposée
(A + A.T) / 2 -> symétrisation
np.trace(A) -> trace de A -> somme des éléments diagonaux
A * A -> multiplication élément par élément
np.dot(A, A)) -> multiplication de matrices

np.linalg.inv(M) -> inversion de matrice
np.linalg.eig -> calcul de vecteurs / valeurs propres
np.linalg.solve -> résolution de système linéaire

opération de réduction:
np.sum(M) -> somme de tous les éléments
np.sum(M[1, :]) -> somme de la deuxième ligne
np.sum(M, axis=1) -> sommes de toutes les lignes
np.sum(M, axis=0) -> sommes de toutes les colonnes
np.mean(M) -> moyenne de tous les éléments
np.var -> variance
np.std -> écart type
np.min -> minimum
np.max -> maximum
np.prod -> produit
np.cumsum -> somme cumulée
np.cumprod -> produit cumulé

B = A -> assignation sans copie
B = a.copy() -> assignation avec copie
A.reshape((x, y)) -> changement de taille
np.tile(A, (1, 2)) -> répéter A une fois en ligne et 2 fois en colonne
np.concatenate((A, B), axis=0))
np.vstack((A, B)) -> égal axis = 0
ng.hstack((A, B.T))

import scipy
-> statistique et traitement du signal, etc.

Décomposition en valeurs singulières (SVD)

import numpy as np
from numpy import linalg
M = np.matrix([[1, 2, 3], [4, 5, 6]])
U, s, W = linalg.svd(M)

# reconstruction de M
S = np.zeros((2, 3), dtype = 'float')
S[:2, :2] = np.diag(s)
S = np.matrix(S)
M_recons = U * S * W

La dernière mise à jour de cette page date de mai 2024.

Le contenu de ce site est, en tant qu'œuvre originale de l'esprit, protégé par le droit d'auteur.
Pour tout commentaire, vous pouvez m'écrire à xavier.lamorlette@gmail.com.