Есть ли аналогичная функция для uniform_filter или convolve scipy.ndimage (аналогичная проблема с Двумерная скользящая средняя Numpy), но среднее значение рассчитывается с использованием только значений во входном массиве (игнорируйте количество значений заполнения для угловых и краевых ячеек). Аналогичная функция, в которой значение заполнения может быть установлено равным np.nan, а результирующее среднее значение рассчитывается как np.nanmean?
Мой исходный код зацикливается на массиве, чтобы получить соседей и вычислить результирующее среднее значение, но этот метод занимает слишком много времени. Я пробовал и uniform_filter, и convolve, но результаты не то, что мне нужно, так как результирующие значения углов и краев слишком малы (из-за заполнения краев 0).
Например, если у меня есть массив:
a = np.ones((4,5))
Вычисление среднего значения из движущегося массива 3x3 также должно привести к:
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
юниформ_фильтр дает:
uniform_filter(a, size=3, mode='constant', cval=0.0)
array([[0.44444444, 0.66666667, 0.66666667, 0.66666667, 0.44444444],
[0.66666667, 1. , 1. , 1. , 0.66666667],
[0.66666667, 1. , 1. , 1. , 0.66666667],
[0.44444444, 0.66666667, 0.66666667, 0.66666667, 0.44444444]])
Я попытался установить cval=np.nan, но результирующие значения краев ячеек равны nan.
Для другого массива b
array([[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
Я хочу получить массив, используя окно усреднения 3x3, как
array([[0.25 , 0.16666667, 0. ],
[0.16666667, 0.11111111, 0. ],
[0. , 0. , 0. ]])
Значения рассчитываются, как показано на этом иллюстрация
Попробуйте изменить код как
uniform_filter(a, size=3, mode='wrap')
Это должно избежать проблемы заполнения нулями значений ребер.
Проверьте это для других режимов, которые вы можете предпочесть: https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.uniform_filter.html
Не могли бы вы предоставить ожидаемый результат. Прямо сейчас вопрос кажется открытым.
Получите оконные суммы и разделите их на действительные элементы в каждом окне. Мы можем использовать scipy.signal.convolve2d
, чтобы получить оба и, следовательно, иметь такое решение:
from scipy.signal import convolve2d
def windowed_average(a, kernel_size, mode='same'):
k = np.ones((kernel_size,kernel_size),dtype=int)
window_sum = convolve2d(a,k,mode)
window_count = convolve2d(np.ones(a.shape, dtype=bool),k,mode)
return window_sum/window_count
Альтернатива №1
В качестве альтернативы, если вы хотите использовать uniform_filter
для получения оконных сумм, мы можем сделать это, и это также может быть более эффективным, например:
from scipy.ndimage import uniform_filter
n = kernel_size**2
window_sum = uniform_filter(a, kernel_size, mode='constant', cval=0.0)*n
Примеры запусков -
In [54]: a
Out[54]:
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
In [55]: windowed_average(a, kernel_size=3)
Out[55]:
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
In [56]: b
Out[56]:
array([[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [57]: windowed_average(b, kernel_size=3)
Out[57]:
array([[0.25 , 0.16666667, 0. ],
[0.16666667, 0.11111111, 0. ],
[0. , 0. , 0. ]])
Я уже пробовал этот и другие режимы. Независимо от значения заполнения, я хотел, чтобы они были замаскированы при расчете среднего значения.