Numpy in python

Tutorial Completo su NumPy

Introduzione a NumPy

NumPy (Numerical Python) è la libreria fondamentale per il calcolo scientifico in Python. Fornisce oggetti array multidimensionali ad alte prestazioni e strumenti per lavorare con questi array.

Perché usare NumPy?

  • Velocità: Le operazioni su array NumPy sono molto più veloci delle liste Python

  • Efficienza: Gestione efficiente della memoria

  • Funzionalità: Ampia collezione di funzioni matematiche

  • Interoperabilità: Base per molte altre librerie scientifiche (Pandas, SciPy, scikit-learn)

Installazione

pip install numpy

Importazione

import numpy as np

1. Creazione di Array

Array da liste Python

# Array 1D
arr1d = np.array([1, 2, 3, 4, 5])
print(arr1d)  # Output: [1 2 3 4 5]

# Array 2D
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
print(arr2d)
# Output:
# [[1 2 3]
#  [4 5 6]]

Array con valori predefiniti

# Array di zeri
zeros = np.zeros((3, 4))
print(zeros)
# Output:
# [[0. 0. 0. 0.]
#  [0. 0. 0. 0.]
#  [0. 0. 0. 0.]]

# Array di uni
ones = np.ones((2, 3))
print(ones)
# Output:
# [[1. 1. 1.]
#  [1. 1. 1.]]

# Array con valore specifico
full = np.full((2, 2), 7)
print(full)
# Output:
# [[7 7]
#  [7 7]]

# Array identità
identity = np.eye(3)
print(identity)
# Output:
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

Array con sequenze

# Array con range
range_arr = np.arange(0, 10, 2)  # start, stop, step
print(range_arr)  # Output: [0 2 4 6 8]

# Array con valori equidistanti
linspace = np.linspace(0, 1, 5)  # start, stop, num elementi
print(linspace)  # Output: [0.   0.25 0.5  0.75 1.  ]

# Array vuoto (contenuto random dalla memoria)
empty = np.empty((2, 3))
print(empty)

Array random

# Numeri random uniformi [0, 1)
random_arr = np.random.random((2, 3))
print(random_arr)

# Numeri random da distribuzione normale
normal_arr = np.random.normal(0, 1, (3, 3))  # media, dev.std, dimensione
print(normal_arr)

# Numeri interi random
int_arr = np.random.randint(0, 10, (2, 4))  # low, high, dimensione
print(int_arr)

2. Proprietà degli Array

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

print("Array:", arr)
print("Dimensione:", arr.shape)      # Output: (2, 3)
print("Numero di dimensioni:", arr.ndim)  # Output: 2
print("Numero totale di elementi:", arr.size)  # Output: 6
print("Tipo dati:", arr.dtype)       # Output: int64

3. Indicizzazione e Slicing

Array 1D

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

print(arr[3])        # Output: 3
print(arr[-1])       # Output: 9
print(arr[2:5])      # Output: [2 3 4]
print(arr[:5])       # Output: [0 1 2 3 4]
print(arr[5:])       # Output: [5 6 7 8 9]
print(arr[::2])      # Output: [0 2 4 6 8]

Array 2D

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

print(arr[0, 1])     # Output: 2 (prima riga, seconda colonna)
print(arr[1])        # Output: [4 5 6] (seconda riga)
print(arr[:, 1])     # Output: [2 5 8] (seconda colonna)
print(arr[0:2, 1:3]) # Output: [[2 3] [5 6]]

Modifica mediante slicing

arr = np.array([0, 1, 2, 3, 4, 5])
arr[1:4] = [10, 20, 30]
print(arr)  # Output: [ 0 10 20 30  4  5]

4. Operazioni Matematiche

Operazioni elemento per elemento

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print(a + b)   # Output: [5 7 9]
print(a - b)   # Output: [-3 -3 -3]
print(a * b)   # Output: [4 10 18]
print(a / b)   # Output: [0.25 0.4 0.5]
print(a ** 2)  # Output: [1 4 9]

Funzioni matematiche

arr = np.array([1, 2, 3])

print(np.sqrt(arr))    # Radice quadrata: [1. 1.414 1.732]
print(np.exp(arr))     # Esponenziale: [2.718 7.389 20.085]
print(np.sin(arr))     # Seno
print(np.log(arr))     # Logaritmo naturale
print(np.abs([-1, -2, 3]))  # Valore assoluto: [1 2 3]

Operazioni di aggregazione

arr = np.array([1, 2, 3, 4, 5])

print(np.sum(arr))        # Somma: 15
print(np.mean(arr))       # Media: 3.0
print(np.std(arr))        # Deviazione standard
print(np.min(arr))        # Minimo: 1
print(np.max(arr))        # Massimo: 5
print(np.argmax(arr))     # Indice del massimo: 4
print(np.argmin(arr))     # Indice del minimo: 0

# Per array multidimensionali
arr2d = np.array([[1, 2], [3, 4]])
print(np.sum(arr2d, axis=0))  # Somma lungo le colonne: [4 6]
print(np.sum(arr2d, axis=1))  # Somma lungo le righe: [3 7]

5. Manipolazione degli Array

Reshape

arr = np.arange(12)
print(arr)  # Output: [ 0  1  2  3  4  5  6  7  8  9 10 11]

reshaped = arr.reshape(3, 4)
print(reshaped)
# Output:
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

# -1 per dimensione automatica
auto_reshape = arr.reshape(2, -1)  # 2 righe, colonne automatiche
print(auto_reshape)

Concatenazione

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])

# Concatenazione verticale
v_concatenated = np.vstack((a, b))
print(v_concatenated)
# Output:
# [[1 2]
#  [3 4]
#  [5 6]]

# Concatenazione orizzontale
c = np.array([[7], [8]])
h_concatenated = np.hstack((a, c))
print(h_concatenated)
# Output:
# [[1 2 7]
#  [3 4 8]]

Split

arr = np.arange(9).reshape(3, 3)
print(arr)
# Output:
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

# Split verticale
sub_arrays = np.vsplit(arr, 3)
for i, sub in enumerate(sub_arrays):
    print(f"Parte {i+1}:\n{sub}")

Transpose

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr)
# Output:
# [[1 2 3]
#  [4 5 6]]

transposed = arr.T
print(transposed)
# Output:
# [[1 4]
#  [2 5]
#  [3 6]]

6. Broadcasting

Il broadcasting permette operazioni tra array di dimensioni diverse:

# Array 2D + Array 1D
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([10, 20, 30])

result = a + b
print(result)
# Output:
# [[11 22 33]
#  [14 25 36]]

# Array 2D + scalare
result2 = a * 2
print(result2)
# Output:
# [[ 2  4  6]
#  [ 8 10 12]]

7. Array Booleani e Filtri

Operazioni booleane

arr = np.array([1, 2, 3, 4, 5])

# Confronti elemento per elemento
print(arr > 3)  # Output: [False False False True True]
print(arr == 2) # Output: [False True False False False]

Filtri booleani

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

# Filtro per elementi > 3
filtered = arr[arr > 3]
print(filtered)  # Output: [4 5 6]

# Filtro con condizioni multiple
filtered2 = arr[(arr > 2) & (arr < 6)]
print(filtered2)  # Output: [3 4 5]

# Filtro con condizione OR
filtered3 = arr[(arr < 3) | (arr > 5)]
print(filtered3)  # Output: [1 2 6]

where()

arr = np.array([1, 2, 3, 4, 5])

# Sostituisce elementi che soddisfano una condizione
result = np.where(arr > 3, 100, arr)
print(result)  # Output: [1 2 3 100 100]

8. Algebra Lineare

# Prodotto di matrici
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

dot_product = np.dot(a, b)
print(dot_product)
# Output:
# [[19 22]
#  [43 50]]

# Determinante
det = np.linalg.det(a)
print(det)  # Output: -2.0

# Inversa
inv = np.linalg.inv(a)
print(inv)
# Output:
# [[-2.   1. ]
#  [ 1.5 -0.5]]

# Autovalori e autovettori
eigenvalues, eigenvectors = np.linalg.eig(a)
print("Autovalori:", eigenvalues)
print("Autovettori:\n", eigenvectors)

9. Input/Output

# Salvare array
arr = np.array([[1, 2, 3], [4, 5, 6]])
np.save('my_array.npy', arr)

# Caricare array
loaded_arr = np.load('my_array.npy')
print(loaded_arr)

# Salvare e caricare in formato testo
np.savetxt('array.txt', arr)
loaded_txt = np.loadtxt('array.txt')
print(loaded_txt)

10. Esempi Pratici

Normalizzazione di dati

data = np.random.normal(0, 10, 100)  # Dati con media 0, dev.std 10

# Normalizzazione z-score
normalized = (data - np.mean(data)) / np.std(data)
print("Media normalizzata:", np.mean(normalized))
print("Dev.std normalizzata:", np.std(normalized))

Manipolazione di immagini (come array)

# Creazione di un'immagine semplice
image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)

# Filtro per rendere l'immagine più scura
dark_image = image // 2

# Filtro per solo canale rosso
red_channel = image.copy()
red_channel[:, :, 1] = 0  # Azzera verde
red_channel[:, :, 2] = 0  # Azzera blu

Risoluzione sistema lineare

# Risolvere: 3x + y = 9, x + 2y = 8
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])

x = np.linalg.solve(A, b)
print(x)  # Output: [2. 3.] -> x=2, y=3


LIST VS NUMPY

Last updated