def test_index_level_leaf_loc_to_iloc_c(self) -> None:

        groups = Index(('A', 'B', 'C'))
        dates = IndexDate.from_date_range('2018-01-01', '2018-01-04')
        observations = Index(('x', 'y'))

        lvl2a = IndexLevel(index=observations)
        lvl2b = IndexLevel(index=observations, offset=2)
        lvl2c = IndexLevel(index=observations, offset=4)
        lvl2d = IndexLevel(index=observations, offset=6)

        lvl2_targets = ArrayGO((lvl2a, lvl2b, lvl2c, lvl2d))

        lvl1a = IndexLevel(index=dates,
                targets=lvl2_targets, offset=0)
        lvl1b = IndexLevel(index=dates,
                targets=lvl2_targets, offset=len(lvl1a))
        lvl1c = IndexLevel(index=dates,
                targets=lvl2_targets, offset=len(lvl1a) * 2)

        lvl0 = IndexLevel(index=groups,
                targets=ArrayGO((lvl1a, lvl1b, lvl1c)))

        with self.assertRaises(KeyError):
            lvl0.leaf_loc_to_iloc(('A'))

        self.assertEqual(lvl0.leaf_loc_to_iloc(('A', '2018-01-01', 'y')), 1)
예제 #2
0
    def test_index_level_leaf_loc_to_iloc_a(self):

        groups = Index(('A', 'B', 'C'))
        dates = IndexDate.from_date_range('2018-01-01', '2018-01-04')
        observations = Index(('x', 'y'))

        lvl2a = IndexLevel(index=observations)
        lvl2b = IndexLevel(index=observations, offset=2)
        lvl2c = IndexLevel(index=observations, offset=4)
        lvl2d = IndexLevel(index=observations, offset=6)

        lvl2_targets = ArrayGO((lvl2a, lvl2b, lvl2c, lvl2d))

        lvl1a = IndexLevel(index=dates,
                targets=lvl2_targets, offset=0)
        lvl1b = IndexLevel(index=dates,
                targets=lvl2_targets, offset=len(lvl1a))
        lvl1c = IndexLevel(index=dates,
                targets=lvl2_targets, offset=len(lvl1a) * 2)

        # we need as many targets as len(index)
        lvl0 = IndexLevel(index=groups,
                targets=ArrayGO((lvl1a, lvl1b, lvl1c)))

        self.assertEqual(lvl0.leaf_loc_to_iloc(('B', '2018-01-04', 'y'),), 15)
        self.assertEqual(lvl0.leaf_loc_to_iloc(('A', '2018-01-01', 'y')), 1)
    def test_index_level_a(self) -> None:
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))
        targets = np.array(
                (IndexLevelGO(index=observations), IndexLevelGO(observations, offset=2)))

        level0 = IndexLevelGO(index=groups, targets=ArrayGO(targets))
        level1 = level0.to_index_level()

        groups = IndexGO(('C', 'D'))
        observations = IndexGO(('x', 'y', 'z'))
        targets = np.array(
                (IndexLevelGO(index=observations), IndexLevelGO(observations, offset=3)))

        level2 = IndexLevelGO(index=groups, targets=ArrayGO(targets))

        with self.assertRaises(RuntimeError):
            level0.extend(IndexLevelGO(index=observations))

        level0.extend(level2)

        self.assertEqual(len(level0.values), 10)
        self.assertEqual(len(level1.values), 4)
        self.assertEqual(len(level2.values), 6)

        assert level0.targets is not None

        self.assertEqual([lvl.offset for lvl in level0.targets], [0, 2, 4, 7])

        self.assertEqual(level2.depth, next(level2.depths()))
예제 #4
0
    def test_index_level_a(self) -> None:
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))
        targets = np.array((IndexLevelGO(index=observations),
                            IndexLevelGO(observations, offset=2)))

        level0 = IndexLevelGO(index=groups, targets=ArrayGO(targets))
        level1 = level0.to_index_level()

        groups = IndexGO(('C', 'D'))
        observations = IndexGO(('x', 'y', 'z'))
        targets = np.array((IndexLevelGO(index=observations),
                            IndexLevelGO(observations, offset=3)))

        level2 = IndexLevelGO(index=groups, targets=ArrayGO(targets))

        level0.extend(level2)

        self.assertEqual(len(level0.get_labels()), 10)
        self.assertEqual(len(level1.get_labels()), 4)
        self.assertEqual(len(level2.get_labels()), 6)

        assert level0.targets is not None

        # import ipdb; ipdb.set_trace()
        self.assertEqual([lvl.offset for lvl in level0.targets], [0, 2, 4, 7])
예제 #5
0
    def test_index_level_append_a(self) -> None:

        category = IndexGO(('I', 'II'))
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))

        lvl2a = IndexLevelGO(index=observations)
        lvl2b = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2a, lvl2b))
        # must defensively copy index
        assert id(lvl2a.index) != id(lvl2b.index)

        lvl1a = IndexLevelGO(index=groups,
                targets=lvl2_targets,
                offset=0)


        # must create new index levels for each lower node
        lvl2c = IndexLevelGO(index=observations)
        lvl2d = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2c, lvl2d))
        # must defensively copy index
        assert id(lvl2c.index) != id(lvl2d.index)

        lvl1b = IndexLevelGO(index=groups,
                targets=lvl2_targets,
                offset=len(lvl1a))

        # we need as many targets as len(index)
        lvl0 = IndexLevelGO(index=category,
                targets=ArrayGO((lvl1a, lvl1b)))

        with self.assertRaises(RuntimeError):
            # RuntimeError: level for extension does not have necessary levels.
            lvl0.extend(lvl1b)

        lvl0.append(('II', 'B', 'z')) # depth not found is 2
        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.values],
                list(range(9)))

        lvl0.append(('II', 'C', 'a')) # depth not found is 1
        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.values],
                list(range(10)))

        lvl0.append(('III', 'A', 'a')) # 0

        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.values],
                list(range(11)))

        self.assertEqual(
                lvl0.values.tolist(),
                [['I', 'A', 'x'], ['I', 'A', 'y'], ['I', 'B', 'x'], ['I', 'B', 'y'], ['II', 'A', 'x'], ['II', 'A', 'y'], ['II', 'B', 'x'], ['II', 'B', 'y'], ['II', 'B', 'z'], ['II', 'C', 'a'], ['III', 'A', 'a']])
예제 #6
0
    def test_level_append_a(self):

        category = IndexGO(('I', 'II'))
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))

        lvl2a = IndexLevelGO(index=observations)
        lvl2b = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2a, lvl2b))
        # must defensively copy index
        assert id(lvl2a.index) != id(lvl2b.index)

        lvl1a = IndexLevelGO(index=groups,
                targets=lvl2_targets,
                offset=0)


        # must create new index levels for each lower node
        lvl2c = IndexLevelGO(index=observations)
        lvl2d = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2c, lvl2d))
        # must defensively copy index
        assert id(lvl2c.index) != id(lvl2d.index)

        lvl1b = IndexLevelGO(index=groups,
                targets=lvl2_targets,
                offset=len(lvl1a))

        # we need as many targets as len(index)
        lvl0 = IndexLevelGO(index=category,
                targets=ArrayGO((lvl1a, lvl1b)))


        lvl0.append(('II', 'B', 'z')) # depth not found is 2
        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.get_labels()],
                list(range(9)))

        lvl0.append(('II', 'C', 'a')) # depth not found is 1
        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.get_labels()],
                list(range(10)))

        lvl0.append(('III', 'A', 'a')) # 0

        self.assertEqual(
                [lvl0.loc_to_iloc(tuple(x)) for x in lvl0.get_labels()],
                list(range(11)))

        self.assertEqual(
                lvl0.get_labels().tolist(),
                [['I', 'A', 'x'], ['I', 'A', 'y'], ['I', 'B', 'x'], ['I', 'B', 'y'], ['II', 'A', 'x'], ['II', 'A', 'y'], ['II', 'B', 'x'], ['II', 'B', 'y'], ['II', 'B', 'z'], ['II', 'C', 'a'], ['III', 'A', 'a']])
    def test_index_level_extend_c(self) -> None:
        observations0 = IndexGO(('x', 'y'))
        targets0 = ArrayGO(
                (IndexLevelGO(index=observations0),
                IndexLevelGO(observations0, offset=2)))
        level0 = IndexLevelGO(index=IndexDateGO(('2021', '2022')), targets=targets0)

        observations1 = IndexGO(('x', 'y'))
        targets1 = ArrayGO(
                (IndexLevelGO(index=observations1),
                IndexLevelGO(observations1, offset=2)))
        level1 = IndexLevelGO(index=IndexYearMonthGO(('1853-03', '1873-12')), targets=targets1)
        # RuntimeError: level for extension does not have corresponding types: <class 'static_frame.core.index_datetime.IndexDateGO'>, <class 'static_frame.core.index_datetime.IndexYearMonthGO'>
        with self.assertRaises(RuntimeError):
            level0.extend(level1)
예제 #8
0
    def test_array_getitem_a(self):

        a = np.array(('a', 'b', 'c', 'd'), object)
        a.flags.writeable = False

        ag1 = ArrayGO(a)
        # insure no copy for immutable
        self.assertEqual(mloc(ag1.values), mloc(a))

        ag1.append('b')

        post = ag1[ag1.values == 'b']

        self.assertEqual(post.tolist(), ['b', 'b'])
        self.assertEqual(ag1[[2, 1, 1, 1]].tolist(), ['c', 'b', 'b', 'b'])
예제 #9
0
    def to_index_level(
        self,
        offset: tp.Optional[int] = 0,
        cls: tp.Optional[tp.Type['IndexLevel']] = None,
    ) -> 'IndexLevel':
        '''
        A deepcopy with optional adjustments, such as a different offset and possibly a different class. The supplied class will be used to construct the IndexLevel instance (as well as internal indices), permitting the production of an IndexLevelGO.

        Args:
            offset: optionally provide a new offset for the copy. This is not applied recursively
        '''
        cls = cls if cls else self.__class__

        index = mutable_immutable_index_filter(cls.STATIC, self.index)

        if self.targets is not None:
            targets: tp.Optional[ArrayGO] = ArrayGO(
                [t.to_index_level(offset=None, cls=cls) for t in self.targets],
                own_iterable=True)
        else:
            targets = None

        offset = self.offset if offset is None else offset
        return cls(
            index=index,  #type: ignore
            targets=targets,
            offset=offset,
            depth_reference=self.depth,
        )
예제 #10
0
    def to_index_level(
        self,
        offset: tp.Optional[int] = 0,
        cls: tp.Type['IndexLevel'] = None,
    ) -> 'IndexLevel':
        '''
        A deepcopy with optional adjustments, such as a different offset and possibly a different class.

        Args:
            offset: optionally provide a new offset for the copy. This is not applied recursively
        '''
        index = self.index.copy()

        if self.targets is not None:
            # targets = np.empty(len(self.targets), dtype=object)
            # for idx, t in enumerate(self.targets):
            #     # offset of None retains existing offset
            #     targets[idx] = t.to_index_level(offset=None, cls=cls)
            targets = ArrayGO(
                [t.to_index_level(offset=None, cls=cls) for t in self.targets],
                own_iterable=True)
        else:
            targets = None

        offset = self.offset if offset is None else offset
        cls = cls if cls else self.__class__
        return cls(index=index, targets=targets, offset=offset)
예제 #11
0
    def _relabel_at_depth(self, mapper: RelabelInput,
                          depth_level: tp.List[int]) -> 'IndexLevel':
        '''
        Returns a new IndexLevel instance with relabeled indices at the specified `depth_level`s according to `mapper`, where `mapper` is a callable or a mapping.

        Note: There is a strong expectation that depth_level is sorted.
        '''
        assert depth_level, "Invalid depth_levels should have already been sanitized"

        if len(depth_level) == 1:
            return self._relabel_at_single_depth(mapper, depth_level[0])

        if depth_level[0] == 0:
            index = self.index.relabel(mapper)
            target_depths = [level - 1 for level in depth_level[1:]]
            own_index = True
        else:
            index = self.index
            target_depths = [level - 1 for level in depth_level]
            own_index = False

        new_targets = np.empty(len(self.targets), dtype=DTYPE_OBJECT)
        for i, target in enumerate(self.targets):
            new_targets[i] = target._relabel_at_depth(mapper, target_depths)

        return self.__class__(index=index,
                              targets=ArrayGO(new_targets, own_iterable=True),
                              offset=self.offset,
                              own_index=own_index,
                              depth_reference=self._depth)
예제 #12
0
    def _relabel_at_single_depth(self, mapper: RelabelInput,
                                 depth_level: int) -> 'IndexLevel':
        '''
        Returns a new IndexLevel instance with relabeled indices at the specified `depth_level` according to `mapper`.

        It will recursive through the internal index levels to apply a `relabel` to all the appropriate indices.
        '''
        if depth_level == 0:
            return self.__class__(index=self.index.relabel(mapper),
                                  targets=self.targets,
                                  offset=self.offset,
                                  own_index=True,
                                  depth_reference=self._depth)

        # This will only happen if `relabel_at_depth` was not given a sorted
        # `depth_level` argument.
        assert self.targets is not None, f"Invalid depth_level={depth_level}"

        new_targets = np.empty(len(self.targets), dtype=DTYPE_OBJECT)
        for i, target in enumerate(self.targets):
            new_targets[i] = target._relabel_at_single_depth(
                mapper, depth_level - 1)

        return self.__class__(index=self.index,
                              targets=ArrayGO(new_targets, own_iterable=True),
                              offset=self.offset,
                              own_index=False,
                              depth_reference=self._depth)
예제 #13
0
        def get_level(level_data, offset=0, depth=0):

            if isinstance(level_data, dict):
                level_labels = []
                targets = np.empty(len(level_data), dtype=object)
                offset_local = 0

                # ordered key, value pairs, where the key is the label, the value is a list or dictionary; enmerate for insertion pre-allocated object array
                for idx, (k, v) in enumerate(level_data.items()):
                    level_labels.append(k)
                    level = get_level(v, offset=offset_local, depth=depth + 1)
                    targets[idx] = level
                    offset_local += len(level)  # for lower level offsetting

                index = get_index(level_labels, depth=depth)
                targets = ArrayGO(targets, own_iterable=True)

            else:  # an iterable, terminal node, no offsets needed
                index = get_index(level_data, depth=depth)
                targets = None

            return cls._LEVEL_CONSTRUCTOR(
                index=index,
                offset=offset,
                targets=targets,
            )
예제 #14
0
    def test_index_level_dtypes_a(self) -> None:
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))
        targets = ArrayGO((IndexLevelGO(index=observations),
                           IndexLevelGO(observations, offset=2)))

        level0 = IndexLevelGO(index=groups, targets=targets)
        self.assertEqual([d.kind for d in level0.dtypes()], ['U', 'U'])
예제 #15
0
    def test_index_level_get_labels_a(self):
        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))
        targets = ArrayGO(
                (IndexLevelGO(index=observations), IndexLevelGO(observations, offset=2)))

        level0 = IndexLevelGO(index=groups, targets=targets)

        self.assertEqual(level0.get_labels().tolist(),
                [['A', 'x'], ['A', 'y'], ['B', 'x'], ['B', 'y']])

        self.assertEqual(level0.get_labels().dtype.kind, 'U')

        groups = IndexGO((1, 2))
        observations = IndexGO((10, 20))
        targets = ArrayGO(
                (IndexLevelGO(index=observations), IndexLevelGO(observations, offset=2)))
        level1 = IndexLevelGO(index=groups, targets=targets)
        self.assertEqual(level1.get_labels().dtype.kind, 'i')
예제 #16
0
    def append(self, key: tp.Sequence[tp.Hashable]) -> None:
        '''Add a single, full-depth leaf loc.
        '''
        # find fist depth that does not contain key
        depth_count = next(self.depths())

        if len(key) != depth_count:
            raise RuntimeError(
                'appending key {} of insufficent depth {}'.format(
                    key, depth_count))

        depth_not_found = -1
        edge_nodes = np.empty(depth_count, dtype=object)

        node = self
        for depth, k in enumerate(key):
            edge_nodes[depth] = node
            # only set on first encounter in descent
            if depth_not_found == -1 and not node.index.__contains__(k):
                depth_not_found = depth
            if node.targets is not None:
                node = node.targets[-1]

        assert depth_not_found != -1
        level_previous = None

        for depth in range(depth_count - 1, depth_not_found - 1, -1):
            node = edge_nodes[depth]
            k = key[depth]
            # print('key', k, 'current edge index', node.index.values)

            if depth == depth_not_found:
                # when at the the depth not found, we always update the index
                node.index.append(k)

                # if we have targets, must update them
                if node.targets is not None:
                    assert level_previous is not None
                    level_previous.offset = node.__len__()
                    node.targets.append(level_previous)

            else:  # depth not found is higher up
                if node.targets is None:
                    # we are at the max depth; will need to create a LevelGO to append in th next level
                    level_previous = IndexLevelGO(index=IndexGO((k, )),
                                                  offset=0,
                                                  targets=None)
                else:
                    # targets = np.empty(1, dtype=object)
                    targets = ArrayGO([
                        level_previous,
                    ], own_iterable=True)
                    level_previous = IndexLevelGO(index=IndexGO((k, )),
                                                  offset=0,
                                                  targets=targets)
예제 #17
0
 def test_array_deepcopy_a(self) -> None:
     ag1 = ArrayGO(np.array(('a', 'b', 'c', 'd'), dtype=object))
     ag1.append('e')
     ag1.extend(('f', 'g'))
     ag2 = copy.deepcopy(ag1)
     self.assertEqual(ag1._array.tolist(),
                      ag2._array.tolist())  #type: ignore
예제 #18
0
    def from_product(
            cls: tp.Type[IH],
            *levels,
            name: tp.Hashable = None) -> IH:  # tp.Iterable[tp.Hashable]
        '''
        Given groups of iterables, return an ``IndexHierarchy`` made of the product of a values in those groups, where the first group is the top-most hierarchy.

        Returns:
            :py:class:`static_frame.IndexHierarchy`

        '''
        indices = []  # store in a list, where index is depth
        for lvl in levels:
            if not isinstance(lvl, Index):  # Index, not IndexBase
                lvl = cls._INDEX_CONSTRUCTOR(lvl)
            indices.append(lvl)

        if len(indices) == 1:
            raise RuntimeError('only one level given')

        # build name from index names, assuming they are all specified
        if name is None:
            name = tuple(index.name for index in indices)
            if any(n is None for n in name):
                name = None

        targets_previous = None

        # need to walk up from bottom to top
        # get depth pairs and iterate over those
        depth = len(indices) - 1
        while depth > 0:
            index = indices[depth]
            index_up = indices[depth - 1]
            # for each label in the next-up index, we need a reference to this index with an offset of that index (or level)
            targets = np.empty(len(index_up), dtype=object)

            offset = 0
            for idx, _ in enumerate(index_up):
                # this level does not have targets, only an index (as a leaf)
                level = cls._LEVEL_CONSTRUCTOR(index=index,
                                               offset=offset,
                                               targets=targets_previous)

                targets[idx] = level
                offset += len(level)
            targets_previous = ArrayGO(targets, own_iterable=True)
            depth -= 1

        level = cls._LEVEL_CONSTRUCTOR(index=index_up,
                                       targets=targets_previous)
        return cls(level, name=name)
예제 #19
0
 def add_level(self, level: tp.Hashable):
     '''Return an IndexHierarchy with a new root level added.
     '''
     if self.STATIC:  # can reuse levels
         levels_src = self._levels
     else:
         levels_src = self._levels.to_index_level()
     levels = self._LEVEL_CONSTRUCTOR(index=self._INDEX_CONSTRUCTOR(
         (level, )),
                                      targets=ArrayGO([levels_src],
                                                      own_iterable=True),
                                      offset=0)
     return self.__class__(levels)
예제 #20
0
    def test_array_copy_a(self):

        ag1 = ArrayGO(np.array(('a', 'b', 'c', 'd'), object))
        ag1.append('e')

        ag2 = ag1.copy()
        ag1.extend(('f', 'g'))

        self.assertEqual(ag1.values.tolist(),
                         ['a', 'b', 'c', 'd', 'e', 'f', 'g'])

        self.assertEqual(ag2.values.tolist(), ['a', 'b', 'c', 'd', 'e'])
예제 #21
0
    def test_index_level_append_b(self) -> None:

        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))
        lvl2a = IndexLevelGO(index=observations)
        lvl2b = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2a, lvl2b))
        lvl1a = IndexLevelGO(index=groups, targets=lvl2_targets, offset=0)

        with self.assertRaises(RuntimeError):
            lvl1a.append((1, 2, 3))

        lvl1a.append((1, 2))
        self.assertEqual(
            lvl1a.values.tolist(),
            [['A', 'x'], ['A', 'y'], ['B', 'x'], ['B', 'y'], [1, 2]])
예제 #22
0
        def get_level(level_data, offset=0):

            if isinstance(level_data, dict):
                level_labels = []
                targets = np.empty(len(level_data), dtype=object)
                offset_local = 0
                for idx, (k, v) in enumerate(level_data.items()):
                    level_labels.append(k)
                    level = get_level(v, offset=offset_local)
                    targets[idx] = level
                    offset_local += len(level)
                index = cls._INDEX_CONSTRUCTOR(level_labels)
                targets = ArrayGO(targets, own_iterable=True)
            else: # an iterable, terminal node, no offsets needed
                targets = None
                index = cls._INDEX_CONSTRUCTOR(level_data)

            return cls._LEVEL_CONSTRUCTOR(index=index, offset=offset, targets=targets)
예제 #23
0
    def test_index_level_deepcopy_a(self) -> None:

        groups = IndexGO(('A', 'B'))
        observations = IndexGO(('x', 'y'))

        lvl2a = IndexLevelGO(index=observations)
        lvl2b = IndexLevelGO(index=observations, offset=2)
        lvl2_targets = ArrayGO((lvl2a, lvl2b))
        assert id(lvl2a.index) != id(lvl2b.index)

        lvl1a = IndexLevelGO(index=groups,
                targets=lvl2_targets,
                offset=0)

        post = copy.deepcopy(lvl1a)
        self.assertEqual(lvl1a.values.tolist(), post.values.tolist())
        self.assertEqual(
                id(post.targets[0].index._labels), #type: ignore
                id(post.targets[1].index._labels)) #type: ignore
예제 #24
0
    def test_array_append_a(self) -> None:

        ag1 = ArrayGO(('a', 'b', 'c', 'd'))

        self.assertEqual([x for x in ag1], ['a', 'b', 'c', 'd'])

        self.assertEqual(ag1.values.tolist(), ['a', 'b', 'c', 'd'])

        ag1.append('e')
        ag1.extend(('f', 'g'))

        self.assertEqual(ag1.values.tolist(),
                         ['a', 'b', 'c', 'd', 'e', 'f', 'g'])

        self.assertEqual([x for x in ag1], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
예제 #25
0
    def test_array_append_b(self):

        ag1 = ArrayGO(np.array(('a', 'b', 'c', 'd'), object))

        self.assertEqual([x for x in ag1], ['a', 'b', 'c', 'd'])

        self.assertEqual(ag1.values.tolist(), ['a', 'b', 'c', 'd'])

        ag1.append('e')
        ag1.extend(('f', 'g'))

        self.assertEqual(ag1.values.tolist(),
                         ['a', 'b', 'c', 'd', 'e', 'f', 'g'])

        self.assertEqual([x for x in ag1], ['a', 'b', 'c', 'd', 'e', 'f', 'g'])
예제 #26
0
    def from_level_data(
        cls,
        level_data: tp.Any,
        get_index: tp.Callable[[IndexInitializer, int], IndexBase],
        offset: int = 0,
        depth: int = 0,
    ) -> 'IndexLevel':
        '''
        Recursive function used in ``from_tree`` constructor.
        '''
        if isinstance(level_data, dict):
            level_labels = []
            targets = np.empty(len(level_data), dtype=object)
            offset_local = 0

            # ordered key, value pairs, where the key is the label, the value is a list or dictionary; enmerate for insertion pre-allocated object array
            for idx, (k, v) in enumerate(level_data.items()):
                level_labels.append(k)
                level = cls.from_level_data(v,
                                            get_index,
                                            offset=offset_local,
                                            depth=depth + 1)
                targets[idx] = level
                offset_local += len(level)  # for lower level offsetting

            index = get_index(level_labels, depth)
            targets = ArrayGO(targets, own_iterable=True)

        else:  # an iterable, terminal node, no offsets needed
            index = get_index(level_data, depth)
            targets = None

        return cls(
            index=index,  #type: ignore
            offset=offset,
            targets=targets,
        )
예제 #27
0
    def from_index_items(
            cls: tp.Type[IH],
            items: tp.Iterable[tp.Tuple[tp.Hashable, Index]],
            *,
            index_constructor: tp.Optional[IndexConstructor] = None) -> IH:
        '''
        Given an iterable of pairs of label, :obj:`Index`, produce an :obj:`IndexHierarchy` where the labels are depth 0, the indices are depth 1.

        Args:
            items: iterable of pairs of label, :obj:`Index`.
            index_constructor: Optionally provide index constructor for outermost index.
        '''
        labels = []
        index_levels = []

        offset = 0
        for label, index in items:
            labels.append(label)

            index = mutable_immutable_index_filter(cls.STATIC, index)
            index_levels.append(
                cls._LEVEL_CONSTRUCTOR(index, offset=offset, own_index=True))
            offset += len(index)

        targets = ArrayGO(np.array(index_levels, dtype=object),
                          own_iterable=True)

        index_outer = index_from_optional_constructor(
            labels,
            default_constructor=cls._INDEX_CONSTRUCTOR,
            explicit_constructor=index_constructor)

        return cls(
            cls._LEVEL_CONSTRUCTOR(index=index_outer,
                                   targets=targets,
                                   own_index=True))
예제 #28
0
    def test_hierarchy_loc_to_iloc_a(self):

        groups = Index(('A', 'B', 'C'))
        dates = IndexDate.from_date_range('2018-01-01', '2018-01-04')
        observations = Index(('x', 'y'))

        lvl2a = IndexLevel(index=observations)
        lvl2b = IndexLevel(index=observations, offset=2)
        lvl2c = IndexLevel(index=observations, offset=4)
        lvl2d = IndexLevel(index=observations, offset=6)
        lvl2_targets = ArrayGO((lvl2a, lvl2b, lvl2c, lvl2d))

        lvl1a = IndexLevel(index=dates, targets=lvl2_targets, offset=0)
        lvl1b = IndexLevel(index=dates,
                           targets=lvl2_targets,
                           offset=len(lvl1a))
        lvl1c = IndexLevel(index=dates,
                           targets=lvl2_targets,
                           offset=len(lvl1a) * 2)

        # we need as many targets as len(index)
        lvl0 = IndexLevel(index=groups, targets=ArrayGO((lvl1a, lvl1b, lvl1c)))

        self.assertEqual(len(lvl2a), 2)
        self.assertEqual(len(lvl1a), 8)
        self.assertEqual(len(lvl0), 24)

        self.assertEqual(list(lvl2a.depths()), [1])
        self.assertEqual(list(lvl1a.depths()), [2, 2, 2, 2])
        self.assertEqual(list(lvl0.depths()),
                         [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3])

        ih = IndexHierarchy(lvl0)

        self.assertEqual(len(ih), 24)

        post = ih.loc_to_iloc(HLoc[['A', 'B', 'C'],
                                   slice('2018-01-01', '2018-01-04'),
                                   ['x', 'y']])
        # this will break if we recognize this can be a slice
        self.assertEqual(post, list(range(len(ih))))

        post = ih.loc_to_iloc(HLoc[['A', 'B', 'C'],
                                   slice('2018-01-01', '2018-01-04'), 'x'])

        self.assertEqual(post, list(range(0, len(ih), 2)))

        post = ih.loc_to_iloc(HLoc['C', '2018-01-03', 'y'])

        self.assertEqual(post, 21)

        post = ih.loc_to_iloc(HLoc['B', '2018-01-03':, 'y'])
        self.assertEqual(post, [13, 15])

        post = ih.loc_to_iloc(HLoc[['B', 'C'], '2018-01-03'])
        self.assertEqual(post, [12, 13, 20, 21])

        post = ih.loc_to_iloc(HLoc[['A', 'C'], :, 'y'])
        self.assertEqual(post, [1, 3, 5, 7, 17, 19, 21, 23])

        post = ih.loc_to_iloc(HLoc[['A', 'C'], :, 'x'])
        self.assertEqual(post, [0, 2, 4, 6, 16, 18, 20, 22])
예제 #29
0
 def test_array_init_a(self) -> None:
     with self.assertRaises(NotImplementedError):
         _ = ArrayGO(np.array((3, 4, 5)))
예제 #30
0
    def test_array_len_a(self):

        ag1 = ArrayGO(np.array(('a', 'b', 'c', 'd'), object))
        ag1.append('e')

        self.assertEqual(len(ag1), 5)