Cálculo médio de elemento numpy para matriz 2D
Sou novo em Python e enfrento um problema de cálculo do valor médio do elemento em um array numpy 2D. Eu pesquisei na web e não encontrei o algoritmo ideal para essas coisas.
Então, por exemplo, eu tenho esta matriz 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]])
Quero obter outro array numpy 2D com os elementos iguais aos valores médios dos elementos da matriz anterior. Além disso, meu objetivo é ter a matriz de saída com a mesma forma da matriz de entrada.
Por exemplo, selecionei um bloco 3 * 3 de elementos de vizinhança e comecei com o primeiro elemento da matriz (zero):
Como é um elemento de 'canto', não podemos calcular a média de 3 * 3, então presumo que podemos calcular a média de 2 * 2: (0 + 1 + 5 + 6): 4 = 3
Em seguida, movemos nosso bloco 3 * 3 para o próximo elemento:
E calcule a média da mesma maneira e assim por diante para a primeira linha da matriz. Movendo linha por linha, elemento por elemento:
E calcule a média da mesma maneira: (0 + 1 + 2 + 5 + 6 + 7 + 10 + 11 + 12): 9 = 6
E assim por diante.
Você poderia me dizer por favor como é possível criar a matriz dos elementos médios com a mesma forma de uma matriz de entrada? Devo operar com loop for com 2 variáveis? E como lidar com elementos de 'fronteira' onde não podemos aplicar bloco 3 * 3 completo de elemento vizinho?
Será muito grato por sua ajuda!
PS Em meus cálculos, presumo ter a matriz de resultado final, para este caso:
Respostas
Se usar scipyfor uma opção, você pode usar uma convolução 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 produz:
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. ]])
como funciona ?
Portanto, a primeira convolução produz a soma do elemento desejado:
array([[ 12, 21, 27, 33, 24],
[ 33, 54, 63, 72, 51],
[ 63, 99, 108, 117, 81],
[ 52, 81, 87, 93, 64]])
E o segundo produz a ponderação (quantos elementos foram somados em cada posição):
array([[4., 6., 6., 6., 4.],
[6., 9., 9., 9., 6.],
[6., 9., 9., 9., 6.],
[4., 6., 6., 6., 4.]])
Você pode fazer sua tarefa usando apenas o Numpy .
Para calcular a média de um elemento e seus vizinhos, defina a seguinte função:
def meanSurroud(arr, r, c):
return np.mean(arr[max(r - 1, 0) : r + 2, max(c - 1, 0) : c + 2])
Em seguida, chame-o para cada índice em sua matriz de origem e salve o resultado em uma matriz de destino:
result = np.empty_like(array, dtype=float)
for ind in np.ndindex(array.shape):
result[ind] = meanSurroud(array, ind[0], ind[1])
O resultado é:
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. ]])