NumPy - people.unica.it - Università di...

41
NumPy Programmazione Orientata agli Oggetti e Scripting in Python

Transcript of NumPy - people.unica.it - Università di...

NumPy

Programmazione Orientata agli Oggettie

Scripting in Python

NumPy: Informazioni di Base

Estensione che aggiunge supporto per vettori e matrici multidimensionali Fornisce:

funzioni matematiche di alto livello con cui operare (algebra lineare, trasformate di Fourier etc.).array multi-dimensionali (ndarray)

Scaricabile dal sito: http://numpy.scipy.org/

Importare il modulo

>>> from numpy import *>>> import numpy >>> import numpy as np

Array

Gli array in NumPy sono omogenei. A differenza delle liste di Python, tutti gli elementi sono dello stesso tipo (dtype).Gestiscono operazioni con dati di elevate dimensioni.Fornisce metodi di accesso, trasformazione, iterazione e inizializzazione di grande efficienza. Generalmente sono più efficienti delle liste convenzionali.Si può creare un array direttamente da una lista o da una tupla.

Array monodimensionali

Creazione di array>>> a = numpy.array([4,7,3]) #array da lista>>> a

array([4, 7, 3])

>>> a = numpy.array((4,7,3)) #array da tupla>>> a

array([4, 7, 3])

>>> a = numpy.array((4,7,3), float) #oppure>>> a = numpy.array((4,7,3), dtype = float)>>> a

array([4., 7., 3.])

>>> a = numpy.array(1,2,3,4) # errore: accetta solo una lista o una tupla!!

Array monodimensionali

Creazione di array>>> a = numpy.arange(10) #simile alla funzione range>>> a

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])>>> a = numpy.arange(1, 4)>>> a array([1, 2, 3])>>> a = numpy.arange(3, 24, 5)>>> a array([ 3,  8, 13, 18, 23])

>>> a.ndim # oppure >>> ndim(a) # numero di “assi” (dimensioni)

1>>> a.shape # oppure >>> shape(a)# numero di elementi per dimensione

(10,)>>> a.size # oppure >>> size(a) # numero di elementi totali

10>>> a.dtype.name # nome del tipo di dato nell’array

'int32'>>> type(a) # tipo della variable a

<type 'numpy.ndarray'>>>> b = a.copy() # oppure >>> b = copy(a) #crea una copia>>> b

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Array: funzioni di base

>>> a = numpy.array([0,1,2,3], int)>>> a[0] #indexing

0>>> a[0] = 10>>> a

array([10, 1, 2, 3])>>> a[0] = 10.6 #attenzione alla (non) conversione!!>>> a

array([10, 1, 2, 3])>>> a.fill(3) #imposta tutti gli elementi con lo stesso valore>>> a

array([3, 3, 3, 3])>>> a[:] = 3 # stesso comportamento di fill, ma più lento>>> a

array([3, 3, 3, 3])

Array: funzioni di base

>>> a= numpy.zeros(5) #array di zeri. Argomento: dimensione dell'array

>>> a

array([ 0., 0., 0., 0., 0.])

>>> a = numpy.zeros(5, int)

>>> a

array([0, 0, 0, 0, 0])

>>> a = numpy.ones(5) #array di 1. Argomento: dimensione dell'array

>>> a

array([ 1., 1., 1., 1., 1.])

>>> a = numpy.ones(5, int)

>>> a

array([1, 1, 1, 1, 1])

Array: funzioni di base

Array multidimensionali

>>> a = numpy.array([[0, 1, 2, 3], [4, 5, 6, 7]])

>>> a array([[0, 1, 2, 3],

[4, 5, 6, 7]])>>> a.shape (2, 4)

>>> a.ndim 2>>> a[1,3] 7>>> a[1,3] = -1

>>> a array([[ 0, 1, 2, 3], [ 4, 5, 6, -1]])>>> a[1] array([ 4, 5, 6, -1])

>>> numpy.zeros((3,3)) array([[ 0., 0., 0.],

[ 0., 0., 0.], [ 0., 0., 0.]])

>>> numpy.ones((3,3)) array([[ 1., 1., 1.],

[ 1., 1., 1.], [ 1., 1., 1.]])

#like

>>> array1 = numpy.array([[1, 2], [3, 4]])

>>> array1 array([[1 2]        [3 4]])

>>> array2 = numpy.zeros_like(array1)

>>> array2 array([[0 0]        [0 0]])

Array multidimensionali

Forma e dimensioni di array

#reshaping

>>> a = np.array(range(10), float)

>>> a array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

>>> a = a.reshape((5, 2))

>>> a array([[ 0., 1.], [ 2., 3.], [ 4., 5.], [ 6., 7.], [ 8., 9.]]) >>> a.shape (5, 2)

Forma e dimensioni di array

#trasposta

>>> a

array([[ 0., 1., 2.],

[ 3., 4., 5.]])

>>> a.transpose()

array([[ 0., 3.], [ 1., 4.], [ 2., 5.]])#vettore

>>> a

array([[ 1., 2., 3.], [ 4., 5., 6.]]) >>> a.flatten()

array([ 1., 2., 3., 4., 5., 6.])

Forma e dimensioni di array

#concatenazione

>>> a = numpy.array([1,2])

>>> b = numpy.array([3,4,5,6])

>>> c = numpy.array([7,8,9])

>>> numpy.concatenate((a, b, c))

array([1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> a = numpy.array([[1, 2], [3, 4]])

>>> b = numpy.array([[5, 6], [7,8]])

>>> numpy.concatenate((a,b))

array([[ 1, 2],

[ 3, 4], [ 5, 6], [ 7, 8]])

>>> numpy.concatenate((a,b), axis=0)

array([[ 1, 2], [ 3, 4], [ 5, 6], [ 7, 8]]) >>> numpy.concatenate((a,b), axis=1)

array([[ 1, 2, 5, 6], [ 3, 4, 7, 8]])

Slicing

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Slicing

>>> a[0,3:5]array([3, 4])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Slicing

>>> a[0,3:5]array([3, 4])

>>> a[4:,4:]array([[44, 45],[54, 55]])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Slicing

>>> a[0,3:5]array([3, 4])

>>> a[4:,4:]array([[44, 45],[54, 55]])

>>> a[:,2]array([2,12,22,32,42,52])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Slicing

>>> a[0,3:5]array([3, 4])

>>> a[4:,4:]array([[44, 45],[54, 55]])

>>> a[:,2]array([2,12,22,32,42,52])

>>> a[2::2,::2]array([[20, 22, 24],[40, 42,

44]])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Slicing

Lo slicing crea delle referenze all'array originale>>> a = array((0,1,2,3,4))

>>> b = a[2:4]

>>> b

array([2,3])

>>> b[0] = 10

>>> b

array([10,3])

# cambio b → cambia a!

>>> a

array([ 1, 2, 10, 3, 4])

Fancy indexing

>>> a = arange(0,80,10)

# fancy indexing per posizione

>>> y = a[[1, 2, -3]]

>>> y

[10 20 50]

# fancy indexing booleano

>>> mask = numpy.array([0,1,1,0,0,1,0,0], dtype=bool)

>>> y = a[mask]

>>> y

[10,20,50]

0 10 20 30 40 50 60 70

10 20 50

a

y

Fancy indexing multidimensionale

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Fancy indexing multidimensionale

>>> a[(0,1,2,3,4),(1,2,3,4,5)] array([ 1, 12, 23, 34, 45])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Fancy indexing multidimensionale

>>> a[(0,1,2,3,4),(1,2,3,4,5)] array([ 1, 12, 23, 34, 45])

>>> a[3:,[0, 2, 5]] array([[30, 32, 35], [40, 42, 45]]) [50, 52, 55]])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Fancy indexing multidimensionale

>>> a[(0,1,2,3,4),(1,2,3,4,5)] array([ 1, 12, 23, 34, 45])

>>> a[3:,[0, 2, 5]] array([[30, 32, 35], [40, 42, 45]]) [50, 52, 55]])

>>> mask = array([1,0,1,0,0,1], dtype=bool) >>> a[mask,2] array([2,22,52])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

Fancy indexing multidimensionale

>>> a[(0,1,2,3,4),(1,2,3,4,5)] array([ 1, 12, 23, 34, 45])

>>> a[3:,[0, 2, 5]] array([[30, 32, 35], [40, 42, 45]]) [50, 52, 55]])

>>> mask = array([1,0,1,0,0,1], dtype=bool) >>> a[mask,2] array([2,22,52])

50 51 52 53 54 55

40 41 42 43 44 45

30 31 32 33 34 35

20 21 22 23 24 25

10 11 12 13 14 15

0 1 2 3 4 5

A differenza dello slicing, il fancy indexing non crea referenze all'array originale, ma crea delle copie

>>> a = array([[1,2,3], [4,5,6]])

# somma di tutti gli elementi.

>>> a.sum()

21

# somma lungo gli assi.

>>> a.sum(axis=0) #primo asse

array([5, 7, 9])

>>> a.sum(axis=-1) #ultimo asse

array([6, 15])

# prodotto di tutti gli elementi.

>>> a.prod()

720

# prodotto lungo il primo asse.

>>> a.prod(axis=0)

array([4, 10, 18])

Array: operazioni di base

>>> a = array([2.,3.,0.,1.])

>>> a.min(axis=) 0.>>> a = array([2.,1.,0.,3.])

>>> a.max(axis=0) 3.#restituisce l'indice dell'elemento di minimo valore.

>>> a.argmin(axis=0) 2#restituisce l'indice dell'elemento di massimo valore.

>>> a.argmax(axis=0) 1>>> a = numpy.array([[1,2,3], [4,5,6]], float)

>>> a.clip(3,5)#valori minori 3 → 3; valori maggiori di 5 → 5.

>>> a

array([[ 3., 3., 3.], [ 4., 5., 5.]])

Array: operazioni di base

Le seguenti funzioni restituiscono il valore intero più vicino, rispettivamente, per difetto, per eccesso e arrotondato

>>> a = np.array([1.1, 1.5, 1.9], float) >>> numpy.floor(a)

array([ 1., 1., 1.])

>>> numpy.ceil(a)

array([ 2., 2., 2.])

>>> numpy.rint(a)

array([ 1., 2., 2.])

Array: operazioni di base

>>> a = numpy.array([[1,2,3], [4,5,6]], float)

#valore medio

>>> a.mean()

3.5

>>> a.mean(axis=0)

array([2.5, 3.5, 4.5])

>>> average(a, axis=0)

array([2.5, 3.5, 4.5])

#deviazione standard

>>> a.std()

1.707825127659933

>>> a.std(axis=0)

array([ 1.5, 1.5, 1.5])

#varianza

>>> a.var()

2.9166666666666665

>>> a.var(axis=0)

array([2.25, 2.25, 2.25])

Array: funzioni statistiche

Gli operatori aritmetici vengono applicati elemento per elemento. Operazioni più efficienti rispetto ad una iterazione elemento per elemento

>>> a = numpy.array([20,30,40,50])>>> b = numpy.arange(4)>>> b array([0, 1, 2, 3])>>> a-b array([20, 29, 38, 47])>>> b*b array([0, 1, 4, 9])>>> b**2 array([0, 1, 4, 9])

Operazioni matematiche

Operazioni matematiche

Corrispondenza tra operatori e funzioni

a + b → numpy.add(a,b)

a - b → numpy.subtract(a,b)

a * b → numpy.multiply(a,b)

a % b → numpy.remainder(a,b)

a / b → numpy.divide(a,b)

a ** b → numpy.power(a,b)

== → numpy.equal(a,b)

!= → numpy.not_equal(a,b)

> → numpy.greater(a,b)

>= → numpy.greater_equal(a,b)

< → numpy.less(a,b)

<= → numpy.less_equal(a,b)

Funzioni

Trigonometrichesin(a)

cos(a)

tan(a)

arcsin(a)

arccos(a)

arctan(a)

sinh(a)

cosh(a)

tanh(a)

arcsinh(a)

arccosh(a)

arctanh(a)

Altre funzioniexp(x)log(x)

log10(x)sqrt(x)

absolute(x)cconjugate(x)

negative(x)ffabs(x) hypot(x,y)fmod(x,y) maximum(x,y)minimum(x,y)

Calcolo matriciale

Prodotto scalare>>> a = numpy.array([1, 2, 3],float) >>> b = numpy.array([0, 1, 1],float) >>> numpy.dot(a, b) 5.0

Le maggiori funzioni per il calcolo matriciale sono comprese nel sotto-modulo linalg

#calcolo del determinante

>>> a = numpy.array([[4, 2, 0], [9, 3, 7], [1, 2, 1]], float)

>>> a

array([[4., 2., 0.],

[9., 3., 7.],

[1., 2., 1.]])

>>> numpy.linalg.det(a)

-53.999999999999993

Calcolo matriciale

#autovalori ed autovettori

>>> vals, vecs = numpy.linalg.eig(a)

>>> vals array([ 9. , 2.44948974, -2.44948974]) >>> vecs array([[-0.3538921 , -0.56786837, 0.27843404], [-0.88473024, 0.44024287, -0.89787873], [-0.30333608, 0.69549388, 0.34101066]]) #matrice inversa

>>> b = numpy.linalg.inv(a)

>>> b array([[0.14814815, 0.07407407, -0.25925926], [0.2037037 , -0.14814815, 0.51851852], [-0.27777778, 0.11111111, 0.11111111]])

Broadcasting

Operazioni tra più elementi di diverse dimensioni. Se possibile tutti gli array vengono convertiti in elementi aventi la stessa dimensioneEsempio:

>>> x = numpy.array([1,2,3,4]) >>> y = numpy.array([[10],[20],[30]]) >>> numpy.add(x,y) [[11 12 13 14] [21 22 23 24] [31 32 33 34]]

Broadcasting

+

30

20

10

0 0 1 2

=

Broadcasting

0 1 2

0 1 2

0 1 2+

0 1 2

30

20

10

0

30

20

10

0

+

30

20

10

0 0 1 2

= =

30

20

10

0

Broadcasting

0 1 2

0 1 2

0 1 2+

0 1 2

30

20

10

0

30

20

10

0

+

30

20

10

0 0 1 2

= =

30

20

10

0

+

0 1 2

0 1 2

0 1 2

0 1 2

30 30 30

20 20 20

10 10 10

0 0 0

+

0 1 2

0 1 2

0 1 2

0 1 2

30 30 30

20 20 20

10 10 10

0 0 0

= =

Broadcasting

0 1 2

0 1 2

0 1 2+

0 1 2

30

20

10

0

30

20

10

0

+

30

20

10

0 0 1 2

= =

30

20

10

0

+

0 1 2

0 1 2

0 1 2

0 1 2

30 30 30

20 20 20

10 10 10

0 0 0

+

0 1 2

0 1 2

0 1 2

0 1 2

30 30 30

20 20 20

10 10 10

0 0 0

= =

30 31 32

20 21 22

10 11 12

0 1 2

=

Broadcasting

Il broadcasting è possibile se il numero di colonne della prima è uguale al numero di righe della seconda, altrimenti l'interprete Python restituisce l'eccezione “ValueError: frames are not aligned”

+

30 30 30

20 20 20

10 10 10

0 0 0 0 1 2

=3

4x3 4

mismatch!

That's all, folks

Nest lesson: Scientific visualization in Python (with matplotlib)