Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

numpy: ndenumerate for masked arrays?

Tags:

python

numpy

Is there a way to enumerate over the non-masked locations of a masked numpy ndarray (e.g. in the way that ndenumerate does it for regular ndarrays, but omitting all the masked entries)?

EDIT: to be more precise: the enumeration should not only skip over the masked entries, but also show the indices of the non-masked ones in the original array. E.g. if the first five elements of a 1-d array are masked, and the next one has an unmasked value of 3, then the enumeration should start with something like ((5,), 3), ....

Thanks!

PS: note that, although it is possible to apply ndenumerate to a masked ndarray, the resulting enumeration does not discriminate between its masked and normal entries. In fact, ndenumerate not only does not filter out the masked entries from the enumeration, but it doesn't even replace the enumerated values with the masked constant. Therefore, one can't adapt ndenumerate for this task by just wrapping ndenumerate with a suitable filter.

like image 985
kjo Avatar asked Dec 23 '11 21:12

kjo


People also ask

What is numpy masked array?

A masked array is the combination of a standard numpy. ndarray and a mask. A mask is either nomask , indicating that no value of the associated array is invalid, or an array of booleans that determines for each element of the associated array whether the value is valid or not.

How can you tell if an array is masked?

To determine whether input has masked values, use the ma. is_masked() method in Python Numpy. Accepts any object as input, but always returns False unless the input is a MaskedArray containing masked values. Returns True if the array is a MaskedArray with masked values, False otherwise.

What is Ndenumerate in Python?

ndenumerate(arr)[source] Multidimensional index iterator. Return an iterator yielding pairs of array coordinates and values.


2 Answers

You can access only valid entries using inverse of a mask as an index:

>>> import numpy as np
>>> import numpy.ma as ma
>>> x = np.array([11, 22, -1, 44])
>>> m_arr = ma.masked_array(x, mask=[0, 0, 1, 0])
>>> for index, i in np.ndenumerate(m_arr[~m_arr.mask]): 
        print index, i
(0,) 11
(1,) 22
(2,) 44

See this for details.

The enumeration over only valid entries with indices from the original array:

>>> for (index, val), m in zip(np.ndenumerate(m_arr), m_arr.mask):
      if not m:
        print index, val 
(0,) 11
(1,) 22
(3,) 44
like image 99
Aleksandra Zalcman Avatar answered Sep 19 '22 10:09

Aleksandra Zalcman


How about:

import numpy as np
import itertools

def maenumerate(marr):
    mask = ~marr.mask.ravel()
    for i, m in itertools.izip(np.ndenumerate(marr), mask):
        if m: yield i

N = 12
a = np.arange(N).reshape(2, 2, 3)+10

b = np.ma.array(a, mask = (a%5 == 0))
for i, val in maenumerate(b):
    print i, val

which yields

(0, 0, 1) 11
(0, 0, 2) 12
(0, 1, 0) 13
(0, 1, 1) 14
(1, 0, 0) 16
(1, 0, 1) 17
(1, 0, 2) 18
(1, 1, 0) 19
(1, 1, 2) 21
like image 44
unutbu Avatar answered Sep 21 '22 10:09

unutbu