Тупой градиент в замаскированном массиве - PullRequest
0 голосов
/ 29 апреля 2018

Когда я вычисляю градиент маскированного массива в numpy как

import numpy as np
import numpy.ma as ma
x = np.array([100, 2, 3, 5, 5, 5, 10, 100])
mx = ma.masked_array(x, mask=[1, 0, 0, 0, 0, 0, 0, 1])

маска результирующего массива отличается от исходной маски:

np.gradient(mx) 
masked_array(data = [-- -- 1.5 1.0 0.0 2.5 -- --],
         mask = [ True  True False False False False  True  True],
   fill_value = 999999)

Почему градиент не вычисляется на «новых» границах? Как я могу это изменить?

Для замаскированных записей в середине это выглядит страннее:

x = np.array([100, 2, 3, 5, 5, 6, 6, 6, 6, 6, 7, 5, 10, 100])
mx = ma.masked_array(x, mask=[1, 0, 0, 0,0, 0,1,0,0,0, 0, 0, 0, 1])
np.gradient(mx)
masked_array(data = [-- -- 1.5 1.0 0.5 -- 0.0 -- 0.0 0.5 -0.5 1.5 ----],
mask = [ True  True False False False  True False  True False False False False
True  True],
fill_value = 1e+20)

Я бы ожидал, что np.gradient будет просто рассматривать замаскированные ячейки как границы.

Обновление:

Что я хочу сделать: Мне нужно вычислить градиент на массиве, а не менять маску или форму массива (в конце я хочу 2d) Маскированные ячейки не должны вносить вклад в градиент. Точки рядом с замаскированной ячейкой должны рассматриваться как границы и применяется односторонняя разница.

- - - - - - - - - - -
- - - - o o - - o - -
- - - o x x o o x o -
- - - o x o - - o - -
- - - - o - - - - - -
- - - - - - - - - - -

В этом эскизе x представляет замаскированную ячейку, а o - ячейки, в которых необходимо вычислить одностороннюю разницу (ячейки по краям области тоже должны быть односторонними, но я не рисую их здесь для ясности).

Ответы [ 2 ]

0 голосов
/ 29 апреля 2018

Я думаю, причина в том, что вы ожидаете, что маскированные элементы массива mx будут пропущены во время вычисления градиента, так что вместо вычисления градиента на x = np.array([100, 2, 3, 5, 5, 5, 10, 100]) мы вычислим его на x = np.array([2, 3, 5, 5, 5, 10]), но реальное поведение отличается тем, что np.ma.MaskedArray наследуется от np.ndarray, а np.gradient() не делает ничего особенного с np.ndarray или его подклассами. Так, в случае mx = ma.masked_array(x, mask=[1, 0, 0, 0, 0, 0, 0, 1]), градиент будет вычислен на массиве:

[--, 2, 3, 5, 5, 5, 10, --]

Сначала он попытается вычислить градиент для первого элемента с разницей первого порядка по умолчанию, а шаг h=1 (по умолчанию np.gradient рассматривает шаги как одинарные в каждом измерении входных данных.):

gradient[0] = (mx[1] - mx[0]) / h

Поскольку это зависит от mx[0], который нельзя использовать с помощью mask, значение gradient[0] будет маскироваться как «True».

Когда он попытается вычислить градиент по индексу 1 для элемента, который вы воспринимаете как новую левую границу массива; этот элемент на самом деле не является граничным элементом ndarray. Когда он вычисляет градиент для элемента, который, по вашему мнению, является новой левой границей, он фактически использует формулу центральных разностей с однородными шагами h, gradient[1] = (mx[2] - mx[0]) / 2h, но поскольку mx[0] маскируется как элемент, который не может быть использован, значение для gradient[1] также не может быть получено, поэтому оно маскируется с помощью True. То же самое происходит на другом конце массива.

Теперь, что касается маскировки чего-то посередине, предположим:

x = np.array([1, 2, 3, 4, 5])
mask = [0, 0, 1, 0, 0]
mx = ma.masked_array(x, mask=mask)    

Функция градиента, примененная к mx снова, будет использовать формулу центральной разности для однородных шагов, и когда мы вычисляем:

masked_gradient[1] = (mx[2] - mx[0]) / 2h
masked_gradient[3] = (mx[4] - mx[2]) / 2h

Ни одно из этих значений не может быть вычислено, поскольку mx [2] маскируется с помощью True. И в то же время:

masked_gradient[2] = (mx[3] - mx[1]) / 2h

Может быть оценено, потому что все значения, от которых он зависит, маскируются как False, поэтому результат будет иметь маску:

[0, 1, 0, 1, 0]

А значения:

[1.0, --, 1.0, --, 1.0]
0 голосов
/ 29 апреля 2018

Он вычисляет центральную разницу , которая не может быть построена рядом с границей (или отсутствующим значением). numpy.gradient переключает на одностороннюю разницу на концах массива, но отверстия маскированного массива не считаются концами.

Ваш второй пример показывает дыру в трафарете: вы можете вычислить ее при изолированной дыре в данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...