import numpy as np
Numpy ajoute le type array qui est similaire à une liste (list) avec la condition supplémentaire que tous les éléments sont du même type. Nous concernant ce sera donc un tableau d’entiers, de flottants voire de booléens.
print(np.array([1.0, 2, "a"]))
f = np.array([1,3,7,10], float)
print(f)
entiers = np.array([1, 3, 7, 8.9], int)
print(entiers)
Sans numpy
Du classique avec une liste compréhension que l'on a déjà écrit plusieurs fois dans ce cours
m = [0 for i in range(10)]
print(m)
m = [ i*i for i in range(10)]
print(m)
Avec numpy
Numpy possède deux fonctions bien pratiques pour initialiser un tableau :
m = np.zeros(10)
print(m)
print type(m)
m = np.ones(10, dtype=int)
print(m)
On remarquera qu'il n'y a pas de caractère de séparation entre les valeurs.
La fonction arange de numpy
m = np.arange(0,10,.5)#arange([debut, fin[, pas)
print(m)
La fonction linspace de numpy
m = np.linspace(1, 10, 10)
print(m)
Sans numpy
tab = []
for i in range(4):
ligne = []
for j in range(5):
ligne.append(0)
tab.append(ligne)
print(tab)
tab = [[0 for row in range(5)]for line in range(4)]
print(tab)
Avec numpy
tab = np.zeros([4,5]) #np.zeros([lines, rows])
print(tab)
Redimensionner un tableau numpy
line = np.linspace(1, 10, 10)
tab = line.reshape(5,2)
print(tab)
tab = np.arange(24).reshape(4,6)
print(tab)
print tab[2,4]
Attributs de dimension
print m.shape # Le nombre de lignes et de colonnes du tableau
print m.size # Le nombre d'éléments dans le tableau
print m.ndim # Dimensions du tableau
Exo n°1 :
Écrire une fonction $generer\_points(n, tmax)$ qui prend en argument un entier $n$ indiquant le nombre de points de coordonnées $(x, y)$ à générer dans une zone géographique carrée plan de largeur $tmax \in\mathbb{N}$. Cette fonction renvoie un tableau numpy de dimension $(n\times 2)$ contenant un ensemble de points généré aléatoirement.
Exo n°2 :
Un robot se dépalce dans cette zone géographique, sa position est initialisée avec une variable globale. Écrire une fonction $get\_position\_robot()$ qui renvoie la position courante du robot et une fonction $set\_position\_robot(pt)$ qui met à jour la position du robot.
Exo n° 3 :
Écrire une fonction $distance\_a\_parcourir(A, B)$ qui prend en paramètre deux points sous forme de leurs coordonnées $[x, y]$ et renvoie la distance à parcourir entre ces deux points.
Exo n°4 :
Écrire une fonction $calculer\_distances(pts)$ qui prend en argument un tableau de $n$ points de type ndarray (comme celui de l'exercice n°1) et renvoie un tableau numpy de dimension ($n\times n$), tel que l’élément d’indice $i,j$ fournit la distance entre les points $i$ et $j$
Sans numpy
def carre(x):
fin = len(x)
for i in range(fin):
x[i] = x[i]**2
return x
%timeit x = range(10000) ; carre(x)
Avec numpy
%timeit x = np.arange(10000) ; x**2
m = [[1,1], [1,1]]
m = m + 1
m = np.ones((2,2))
m = m + 1
print m
p = 5
print m*p
Les tableaux sont importants parce qu’ils vous permettent de réaliser des opérations de traitement par lots sur des données sans écrire de boucles.
Cela est généralement appelé vectorisation.
Remplacer une boucle for sur une liste par une opération sur tableau entraîne un important gain de performance , mais cela peut aussi demander de reformuler le problème.
import matplotlib.pyplot as plt
def f(x):
return x + np.cos(x)**2
x = np.linspace(-2, 2, 100)
y = f(x)
plt.plot(x,y)
plt.grid()
plt.show()
On continue d'utiliser la fonction append mais attention :
help(np.append)
Axis = None
print(m)
np.append(m, 24)
np.append(m, [25, 26, 27, 28, 29, 30])
print(m)
m = np.append(m, [25, 26, 27, 28, 29, 30])
print(m)
Axis = 0 Ajouter une ligne
m = np.arange(24).reshape(4,6)
np.append(m, [[0, 0, 0, 0, 0, 0]], axis=0)
Attention les valeurs ajoutées doivent être contenues dans un tableau de même dimension
Axis = 1 Ajouter une colonne
np.append(m, [[0], [0], [0], [0]], axis=1)
Liste simple
m = [i for i in range(15)]
print type(m), m
m = np.asarray(m, dtype = float)
print type(m)
m = m.reshape(3,5)
print m
Liste 2-D
m = [[i for i in range(5)] for j in range(3)] print type(m), m m = np.asarray(m, dtype = float) print type(m) print m
Si $A = (a_{ij})_{ \begin{array}{c}1\leq i\leq m\\1\leq j\leq n \end{array}}$ et $B = (b_{ij})_{ \begin{array}{c}1\leq i\leq m\\1\leq j\leq n \end{array}}$ sont deux matrices $m \times n$, on définit l’addition des matrices par $$A + B = (a_{ij} + b_{ij})_{ \begin{array}{c}1\leq i\leq m\\1\leq j\leq n \end{array}}$$
Si $A = (a_{ik})_{ \begin{array}{c}1\leq i\leq m\\1\leq k\leq n \end{array}}$ et $B = (b_{kj})_{ \begin{array}{c}1\leq k\leq n\\1\leq j\leq p \end{array}}$ sont deux matrices $m \times n$ et $n \times p$, on définit le produit des matrices par $$A \times B = \left( \sum_{\substack{k=1}}^n a_{ik}\times b_{kj} \right)_{ \begin{array}{c}1\leq i\leq m\\1\leq j\leq p \end{array}}$$
La somme sans numpy
a = [[-1, 4, 1],[0, 1, 1]]
b = [[1, 3, -1],[1, 5, 8]]
def matSum(a, b):
try: #En cas de non respect de cette condition une erreur est levée
assert len(a)==len(b) and len(a[0])==len(b[0])
except AssertionError: #Traitement de l'erreur
print "Les matrices n'ont pas la meme dimension" #Message d'erreur
s = [[0 for i in a[0]] for j in a]
for i in range(len(a)):
for j in range(len(a[0])):
s[i][j] = a[i][j] + b[i][j]
return s
matSum(a, b)
La somme avec numpy
a = np.asarray(a)
b = np.asarray(b)
print(a+b)
c = np.array([[-1, 4],[0, 1]])
d = np.array([[1, 3],[1, 5]])
print(c + d)
Le produit sans numpy
Pour chaque ligne de A on parcourt toutes les colonnes de B. Le nombre d'éléments d'une ligne de A doit être égal au nombre d'éléments d'une colone de B. En d'autres termes le nombre de colonnes de A doit être égal au nombre de lignes de B
Pour une ligne et une colonne donnée on effectue la somme des produits : $a_{ik}$ et $b_{kj}$ avec $k\in [1, n]$
Figure extraite d'un cours de : Gloria Faccanoni
<img src="images/produit.png" width=600 ; height = 600>
def matProd(a, b):
m, n1 = len(a), len(a[0])
n2, p = len(b), len(b[0])
try: # mn * np = mp
assert n1 == n2
except AssertionError:
print "Les matrices n'ont pas les bonnes dimensions"
s = [[0 for i in b[0]] for j in a]
for i in range(m): # Les lignes de A
for j in range(p): # Les colonnes de B
for k in range(n1):
s[i][j] += a[i][k] * b[k][j] # Résultat du produit d'une ligne A par une colonne B
return s
Exemple 1:
a = [[1, 3, 0], [-1, 1, 2]]
b = [[1, 2, 0], [0, 2, 3], [0, -1, -2]]
matProd(a, b)
Exemple 2 : $(A\times B) \neq (B\times A)$
a = [[1, -1], [3, 0]]
b = [[6, -5], [2, 1]]
print matProd(a, b)
print matProd(b, a)
Le Produit avec numpy
Attention comme pour la somme le produit se fait terme à terme
c = np.asarray(a)
d = np.asarray(b)
print c*d
Utilisation du slicing
def matProd(a,b):
lines, columns = len(a), len(b[0])
s = np.zeros((lines, columns))
#return np.asarray([[sum(a[i,:]*b[:,j]) for j in range(columns)]for i in range(lines)])
for i in range(lines):
for j in range(columns):
s[i,j] = sum(a[i,:]*b[:,j]) # Produit terme à terme pour une ligne de A et une colonne de B puis on somme
return s
a = np.array([[1, 3, 0], [-1, 1, 2]])
b = np.array([[1, 2, 0], [0, 2, 3], [0, -1, -2]])
print(matProd(a, b))
print matProd(c, d)
print matProd(d, c)
t = np.loadtxt ( "fichiers/loto.csv" , delimiter = ',')
print t
Avec le sclicing
print t[:,0]
print t[:,0:1]
help(np.savetxt)
Comment référencer une image avec numpy ?
from PIL import Image
#chemin_absolu = "/chemin_depuis_la_racine/"
src = Image.open("images/chaplin.png")
#dst = Image.new("L",src.size)
width, height = src.size
print width, height
src_data = np.asarray(src.getdata()).reshape(height, width)
src.show()
On modifie l'intensité de niveau de gris sur la totalité de l'image
src_data = src_data + 100
src_data = src_data.flatten().tolist()
src.putdata(src_data)#De la liste vers l'image
src.show()
On applique un effet de moiré avec le slicing sur les pixels définis par l'expression [::2,::2]
tmp = src_data[::2,::2] #effet moiré
tmp *= 1.2
tmp += 100
src_data = src_data.flatten().tolist()
src.putdata(src_data)#De la liste vers l'image
src.show()
On modifie uniquement la luminosité de la zone centrale avec l'expression [height/6: 5height/6,width/6: 5width/6]
tmp = src_data[height/6: 5*height/6,width/6: 5*width/6]
tmp *= 1.2
tmp += 100
src_data = src_data.flatten().tolist()
src.putdata(src_data)#De la liste vers l'image
src.show()