ak.layout.ByteMaskedArray — Awkward Array documentation

# ak.layout.ByteMaskedArray

The ByteMaskedArray implements an ak.types.OptionType with two aligned arrays, a boolean `mask` and `content`. At any element `i` where `mask[i] == valid_when`, the value can be found at `content[i]`. If `mask[i] != valid_when`, the value is missing (None).

This is equivalent to NumPy’s masked arrays if `valid_when=False`.

There is no Apache Arrow equivalent because Arrow uses bitmaps to mask all node types.

Below is a simplified implementation of a ByteMaskedArray class in pure Python that exhaustively checks validity in its constructor (see ak.is_valid) and can generate random valid arrays. The `random_number()` function returns a random float and the `random_length(minlen)` function returns a random int that is at least `minlen`. The `RawArray` class represents simple, one-dimensional data.

    class ByteMaskedArray(Content):
        def __init__(self, mask, content, valid_when):
            assert isinstance(mask, list)
            assert isinstance(content, Content)
            assert isinstance(valid_when, bool)
            for x in mask:
                assert isinstance(x, bool)
            assert len(mask) <= len(content)
            self.mask = mask
            self.content = content
            self.valid_when = valid_when

        @staticmethod
        def random(minlen, choices):
            mask = []
            for i in range(random_length(minlen)):
                mask.append(bool(random.randint(0, 1)))
            content = random.choice(choices).random(len(mask), choices)
            return ByteMaskedArray(mask, content, bool(random.randint(0, 1)))

        def __len__(self):
            return len(self.mask)

        def __getitem__(self, where):
            if isinstance(where, int):
                assert 0 <= where < len(self)
                if self.mask[where] == self.valid_when:
                    return self.content[where]
                else:
                    return None
            elif isinstance(where, slice) and where.step is None:
                return ByteMaskedArray(self.mask[where.start:where.stop],
                                       self.content[where.start:where.stop],
                                       valid_when=self.valid_when)
            elif isinstance(where, str):
                return ByteMaskedArray(self.mask, self.content[where], valid_when=self.valid_when)
            else:
                raise AssertionError(where)

        def __repr__(self):
            return ("ByteMaskedArray(" + repr(self.mask) + ", " + repr(self.content)
                    + ", " + repr(self.valid_when) + ")")

        def xml(self, indent="", pre="", post=""):
            out = indent + pre + "<ByteMaskedArray>\n"
            out += indent + "    <valid_when>" + repr(self.valid_when) + "<valid_when>\n"
            out += indent + "    <mask>" + " ".join(str(x) for x in self.mask) + "</mask>\n"
            out += self.content.xml(indent + "    ", "<content>", "</content>\n")
            out += indent + "</ByteMaskedArray>\n"
            return out

Here is an example:

    ByteMaskedArray([True, True, False, False, True, False, False, True, True, True, True, True],
                    RawArray([5.7, 4.5, 8.3, 4.1, 5.1, 4.1, 0.3, 6.4, 5.5, 9.5, 7.1, 7.7, 4.0,
                              4.8, 4.4, 2.9, 1.4, 4.8, 7.3, 4.9, 6.0, 0.6, 11.2, 6.1, 4.7, 4.1,
                              4.4, 5.9, 7.6, 6.3, 5.5, 11.0, 9.2, 5.3, 0.1, 1.2, 4.5, 6.4, 2.8,
                              1.4, 5.8]),
                    False)

    <ByteMaskedArray>
        <valid_when>False</valid_when>
        <mask>True True False False True False False True True True True True</mask>
        <content><RawArray>
            <ptr>5.7 4.5 8.3 4.1 5.1 4.1 0.3 6.4 5.5 9.5 7.1 7.7 4.0 4.8 4.4 2.9 1.4 4.8 7.3 4.9
                 6.0 0.6 11.2 6.1 4.7 4.1 4.4 5.9 7.6 6.3 5.5 11.0 9.2 5.3 0.1 1.2 4.5 6.4 2.8
                 1.4 5.8</ptr>
        </RawArray></content>
    </ByteMaskedArray>

which represents the following logical data.

    [None, None, 8.3, 4.1, None, 4.1, 0.3, None, None, None, None, None]

In addition to the properties and methods described in ak.layout.Content, a ByteMaskedArray has the following.

## ak.layout.ByteMaskedArray.__init__

ak.layout.ByteMaskedArray.__init__(mask, content, valid_when, identities=None, parameters=None)

## ak.layout.ByteMaskedArray.mask

ak.layout.ByteMaskedArray.mask

## ak.layout.ByteMaskedArray.content

ak.layout.ByteMaskedArray.content

## ak.layout.ByteMaskedArray.valid_when

ak.layout.ByteMaskedArray.valid_when

## ak.layout.ByteMaskedArray.project

ak.layout.ByteMaskedArray.project(mask=None)

Returns a non-ak.types.OptionType array containing only the valid elements. If `mask` is a signed 8-bit ak.layout.Index in which `0` means valid and `1` means missing, this `mask` is unioned with the ByteMaskedArray’s mask (after converting to `valid_when=False` to match this `mask`).

## ak.layout.ByteMaskedArray.bytemask

ak.layout.ByteMaskedArray.bytemask()

Returns an array of 8-bit values in which `0` means valid and `1` means missing.

## ak.layout.ByteMaskedArray.simplify

ak.layout.ByteMaskedArray.simplify()

Combines this node with its `content` if the `content` also has ak.types.OptionType; otherwise, this is a pass-through. In all cases, the output has the same logical meaning as the input.

This method only operates one level deep.