НП.где и замаскированный массив


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

Мой маскированный массив:

m_pt0 = np.ma.masked_array([1, 2, 3, 0, 4, 7, 6, 5],
                           mask=[False, True, False, False,
                                 False, False, False, False])

И печатает вот так:

In [24]: print(m_pt0)
[1 -- 3 0 4 7 6 5]

И я ищу индекс в m_pt0, где m_pt0 = 0, я ожидал бы, что

np.where(0 == m_pt0)

Вернет:

(array([3]))
Однако, несмотря на маску (или из-за нее?), Я вместо этого получаю
(array([1, 3]),)

Весь смысл использования маска предназначена для того, чтобы избежать доступа к индексам, которые являются "пустыми", поэтому как я могу использовать where (или другую функцию) только для извлечения индексов, которые не маскируются и соответствуют моим булевым критериям.

2 2

2 ответа:

Необходимо использовать маскированный вариант функции where(), иначе она вернет неправильные или нежелательные результаты для маскированных массивов. То же самое относится и к другим функциям, таким как polyfit().

То есть:

In [2]: np.ma.where(0 == m_pt0)
Out[2]: (array([3]),)

Тест на равенство может создать путаницу. В результате получается еще один маскированный массив:

In [19]: 0 == m_pt0
Out[19]: 
masked_array(data = [False -- False True False False False False],
             mask = [False  True False False False False False False],
       fill_value = True)

Маскируемый массив имеет атрибуты .data и .mask. numpy функции, которые не осознают MA, просто видят .data:

In [20]: _.data
Out[20]: array([False,  True, False,  True, False, False, False, False], dtype=bool)

np.where видит 2 True и возвращает

In [23]: np.where(0 == m_pt0)
Out[23]: (array([1, 3], dtype=int32),)
In [24]: np.where((0 == m_pt0).data)
Out[24]: (array([1, 3], dtype=int32),)

По возможности лучше использовать версию функции np.ma:

In [25]: np.ma.where(0 == m_pt0)
Out[25]: (array([3], dtype=int32),)

Глядя на код для np.source(np.ma.where) я вижу, что он делает

if missing == 2:
    return filled(condition, 0).nonzero()
(plus lots of code for the 3 argument use)

Что filled делает:

In [27]: np.ma.filled((0 == m_pt0),0)
Out[27]: array([False, False, False,  True, False, False, False, False], dtype=bool)

MA функции часто заменяйте замаскированные значения чем-то безобидным (0 в данном случае) или используйте compressed, чтобы удалить их из рассмотрения.

In [36]: m_pt0.compressed()
Out[36]: array([1, 3, 0, 4, 7, 6, 5])
In [37]: m_pt0.filled(100)
Out[37]: array([  1, 100,   3,   0,   4,   7,   6,   5])

Функция numpy будет корректно работать на MA, если она делегирует работу собственному методу массива.

In [41]: np.nonzero(m_pt0)
Out[41]: (array([0, 2, 4, 5, 6, 7], dtype=int32),)
In [42]: m_pt0.nonzero()
Out[42]: (array([0, 2, 4, 5, 6, 7], dtype=int32),)
In [43]: np.where(m_pt0)
Out[43]: (array([0, 1, 2, 4, 5, 6, 7], dtype=int32),)

np.nonzero делегаты. np.where нет.


repr маскируемого массива показывает маску. Его str просто показывает замаскированные данные:

In [31]: m_pt0
Out[31]: 
masked_array(data = [1 -- 3 0 4 7 6 5],
             mask = [False  True False False False False False False],
       fill_value = 999999)
In [32]: str(m_pt0)
Out[32]: '[1 -- 3 0 4 7 6 5]'