Python: средние значения в 2D-массиве

Я хочу создать двумерный массив в Python, и мне хотелось бы перебрать каждый элемент и взять среднее значение. Элемент i должен быть усреднен с использованием 8 окружающих элементов массива (включая элемент i).

Я сгенерировал двумерный массив с рамкой из нулей, используя Формирование рамки из нулей вокруг матрицы в Python.

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
x,y = A.shape
n = 1    
B = np.zeros((x+2*n,y+2*n),dtype=int)
B[n:x+n, n:y+n] = A
print(B)

Как проще всего взять среднее значение?

🤔 А знаете ли вы, что...
В Python есть множество библиотек и фреймворков для разработки веб-приложений.


1
78
4

Ответы:

Получите каждую подматрицу и возьмите среднее значение. Сохраните результаты в отдельной матрице (иначе ранее вычисленное среднее испортит расчет следующего среднего):

Код:

import numpy as np

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
x,y = A.shape
n = 1    
B = np.zeros((x+2*n,y+2*n),dtype=float)
B[n:x+n, n:y+n] = A

C = B.copy() # not doing it in-place because the math would get messed up
for i in range(x):
    for j in range(y):
        sub_b = B[i:i+x, j:j+y]
        average = np.sum(sub_b) / 9
        C[i + n, j + n] = average
        
print(C)

Выход:

[[0.         0.         0.         0.         0.        ]
 [0.         1.33333333 2.33333333 1.77777778 0.        ]
 [0.         3.         5.         3.66666667 0.        ]
 [0.         2.66666667 4.33333333 3.11111111 0.        ]
 [0.         0.         0.         0.         0.        ]]

Чтобы вычислить среднее значение каждого элемента в 2D-массиве, включая 8 окружающих его элементов (и самого себя), вы можете использовать свертку с ядром, которое представляет окружающие элементы. Вот как вы можете это сделать:

  1. Создайте исходный массив с кадром из нулей: у вас уже есть массив «B».

  2. Перебрать массив и вычислить среднее значение:

Код:

import numpy as np
from scipy.ndimage import convolve

#Original 2D array
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

#Create a frame of zeros around the original array
x, y = A.shape
n = 1    
B = np.zeros((x + 2*n, y + 2*n), dtype=int)
B[n:x+n, n:y+n] = A
print("Array with zero padding:")
print(B)

#Define the 3x3 kernel for averaging
kernel = np.ones((3, 3))
averaged_array = convolve(B, kernel, mode='constant', cval=0.0) / 9.0

#Remove the zero padding to get the averaged result for the original array
averaged_result = averaged_array[n:x+n, n:y+n]
print("\nAveraged array:")
print(averaged_result)

Это можно сделать относительно просто, используя ядро ​​(фильтр) 3x3 в вашем массиве, а также правильно проверив, сколько соседей на самом деле имеет каждый элемент (например, края и углы), прежде чем делить, чтобы найти среднее значение.

from scipy.ndimage import convolve
import numpy as np

array = ...

kernel = np.array([[1,1,1],
                   [1,1,1],
                   [1,1,1]])

sum_neighbour = convolve(array, kernel, mode='constant', cval=0.0)

neighbour_count = convolve(np.ones_like(array), kernel, mode='constant', cval=0.0)

avg = sum_neighbour / neighbour_count

бывший:

матрица:

1,2,3,4
5,6,7,8
9,10,11,12,
13,14,15,16

имеет количество соседей:

4,6,6,4
6,9,9,6
6,9,9,6
4,6,6,4

сумма:

14, 24, 30, 22
33, 54, ...

среднее:

3.5, 4, 5, 5.5
5.5, 6.0, ...

Решено

Вам нужна 2D-свертка, используйте scipy.signal.convolve2d с numpy.ones, чтобы получить сумму:

from scipy.signal import convolve2d

out = convolve2d(B, np.ones((3, 3), dtype='int'), mode='same')

Выход:

array([[ 1,  3,  6,  5,  3],
       [ 5, 12, 21, 16,  9],
       [12, 27, 45, 33, 18],
       [11, 24, 39, 28, 15],
       [ 7, 15, 24, 17,  9]])

Если вам нужна небольшая матрица, не нужно дополнять ее нулями:

convolve2d(A, np.ones((3, 3), dtype='int'), mode='same')

# array([[12, 21, 16],
#        [27, 45, 33],
#        [24, 39, 28]])

Для получения среднего повторите ту же операцию с массивом и разделите:

kernel = np.ones((3, 3), dtype='int')
out = (convolve2d(A, kernel, mode='same')
      /convolve2d(np.ones_like(A), kernel, mode='same')
      )

выход:

array([[3. , 3.5, 4. ],
       [4.5, 5. , 5.5],
       [6. , 6.5, 7. ]])