Calcolo della media numpy per elemento per array 2D
Sono nuovo in Python e devo affrontare un problema di calcolo del valore medio in termini di elemento nell'array numpy 2D. Ho cercato nel web e non ho trovato l'algoritmo ottimale per questa roba.
Quindi, ad esempio, ho questo array 2D:
array = np.arange(20).reshape(4,5)
array
Out[7]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
Voglio ottenere un altro array numpy 2D con gli elementi uguali ai valori medi per elemento della matrice precedente. Inoltre, il mio obiettivo è avere la matrice di output con la stessa forma della matrice di input.
Ad esempio, ho selezionato un blocco 3 * 3 di elementi di vicinato e inizio con il primo elemento di matrice (zero):
Dato che è un elemento 'angolo' non possiamo calcolare la media di 3 * 3, quindi presumo che possiamo calcolare la media di 2 * 2: (0 + 1 + 5 + 6): 4 = 3
Quindi spostiamo il nostro blocco 3 * 3 sull'elemento successivo:
E calcola la media allo stesso modo e così via per la prima riga della matrice. Spostamento riga per riga, elemento per elemento:
E calcola la loro media allo stesso modo: (0 + 1 + 2 + 5 + 6 + 7 + 10 + 11 + 12): 9 = 6
E così via.
Puoi dirmi per favore come è possibile creare la matrice degli elementi medi con la stessa forma di una matrice di input? Devo farlo funzionare con il ciclo for con 2 variabili? E come trattare gli elementi "confine" in cui non possiamo applicare il blocco completo 3 * 3 dell'elemento vicino?
Sarà davvero apprezzato per il tuo aiuto!
PS Sui miei calcoli presumo di avere la matrice del risultato finale, per questo caso:
Risposte
Se l'utilizzo scipyè un'opzione, puoi utilizzare una convoluzione 2D :
import numpy as np
from scipy import signal
# Example input
x = np.array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
# The moving window
y = np.ones((3,3))
# We convolve x with y and then we normalize those value with another convolution
# | first convolution |/| second convolution |
r = signal.convolve2d(x,y,mode='same')/signal.convolve2d(np.ones(x.shape),y,mode='same')
E produce:
array([[ 3. , 3.5, 4.5, 5.5, 6. ],
[ 5.5, 6. , 7. , 8. , 8.5],
[10.5, 11. , 12. , 13. , 13.5],
[13. , 13.5, 14.5, 15.5, 16. ]])
come funziona ?
Quindi la prima convoluzione produce la somma dell'elemento desiderato:
array([[ 12, 21, 27, 33, 24],
[ 33, 54, 63, 72, 51],
[ 63, 99, 108, 117, 81],
[ 52, 81, 87, 93, 64]])
E il secondo produce la ponderazione (quanti elementi sono stati sommati in ogni posizione):
array([[4., 6., 6., 6., 4.],
[6., 9., 9., 9., 6.],
[6., 9., 9., 9., 6.],
[4., 6., 6., 6., 4.]])
Puoi svolgere il tuo compito usando esclusivamente Numpy .
Per calcolare la media di un elemento e dei suoi vicini, definire la seguente funzione:
def meanSurroud(arr, r, c):
return np.mean(arr[max(r - 1, 0) : r + 2, max(c - 1, 0) : c + 2])
Quindi chiamalo per ogni indice nell'array di origine e salva il risultato in un array di destinazione:
result = np.empty_like(array, dtype=float)
for ind in np.ndindex(array.shape):
result[ind] = meanSurroud(array, ind[0], ind[1])
Il risultato è:
array([[ 3. , 3.5, 4.5, 5.5, 6. ],
[ 5.5, 6. , 7. , 8. , 8.5],
[10.5, 11. , 12. , 13. , 13.5],
[13. , 13.5, 14.5, 15.5, 16. ]])