ak.layout.IndexedOptionArray

The IndexedOptionArray concept is implemented in 2 specialized classes:

  • ak.layout.IndexOptionArray64: index values 64-bit signed integers.

  • ak.layout.IndexOptionArray32: index values are 32-bit signed integers.

The IndexedOptionArray class is an ak.layout.IndexedArray for which negative values in the index are interpreted as missing. It represents ak.types.OptionType data like ak.layout.ByteMaskedArray, ak.layout.BitMaskedArray, and ak.layout.UnmaskedArray, but the flexibility of the arbitrary index makes it a common output of many operations.

IndexedOptionArray doesn’t have a direct equivalent in Apache Arrow.

Below is a simplified implementation of a IndexedOptionArray 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 IndexedOptionArray(Content):
    def __init__(self, index, content):
        assert isinstance(index, list)
        assert isinstance(content, Content)
        for x in index:
            assert isinstance(x, int)
            assert x < len(content)   # index[i] may be negative
        self.index = index
        self.content = content

    @staticmethod
    def random(minlen, choices):
        content = random.choice(choices).random(0, choices)
        index = []
        for i in range(random_length(minlen)):
            if len(content) == 0 or random.randint(0, 4) == 0:
                index.append(-random_length(1))   # a random number, but not necessarily -1
            else:
                index.append(random.randint(0, len(content) - 1))
        return IndexedOptionArray(index, content)

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

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

    def __repr__(self):
        return "IndexedOptionArray(" + repr(self.index) + ", " + repr(self.content) + ")"

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

Here is an example:

IndexedOptionArray([-30, 19, 6, 7, -3, 21, 13, 22, 17, 9, -12, 16],
                   RawArray([5.2, 1.7, 6.7, -0.4, 4.0, 7.8, 3.8, 6.8, 4.2, 0.3, 4.6, 6.2,
                             6.9, -0.7, 3.9, 1.6, 8.7, -0.7, 3.2, 4.3, 4.0, 5.8, 4.2, 7.0,
                             5.6, 3.8]))
<IndexedOptionArray>
    <index>-30 19 6 7 -3 21 13 22 17 9 -12 16</index>
    <content><RawArray>
        <ptr>5.2 1.7 6.7 -0.4 4.0 7.8 3.8 6.8 4.2 0.3 4.6 6.2 6.9 -0.7 3.9 1.6 8.7 -0.7 3.2
             4.3 4.0 5.8 4.2 7.0 5.6 3.8</ptr>
    </RawArray></content>
</IndexedOptionArray>

which represents the following logical data.

[None, 4.3, 3.8, 6.8, None, 5.8, -0.7, 4.2, -0.7, 0.3, None, 8.7]

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

ak.layout.IndexedOptionArray.__init__

ak.layout.IndexedOptionArray.__init__(index, content, identities=None, parameters=None)

ak.layout.IndexedOptionArray.index

ak.layout.IndexedOptionArray.index

ak.layout.IndexedOptionArray.content

ak.layout.IndexedOptionArray.content

ak.layout.IndexedOptionArray.isoption

ak.layout.IndexedOptionArray.isoption

Returns True because this is an IndexedOptionArray.

ak.layout.IndexedOptionArray.project

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

Returns a non-ak.types.OptionType array containing only the valid elements with the index applied to reorder/duplicate 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 BitMaskedArray’s mask (after converting to 8-bit and to valid_when=False to match this mask).

ak.layout.IndexedOptionArray.bytemask

ak.layout.IndexedOptionArray.bytemask()

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

ak.layout.IndexedOptionArray.simplify

ak.layout.IndexedOptionArray.simplify()

Combines this node with its content if the content also has ak.types.OptionType or is an ak.layout.IndexedArray; 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.